Когда мне следует освобождать объекты в -(void)viewDidUnload, а не в -dealloc?
Что -(void)viewDidUnload
это хорошо для?
Могу ли я не просто рассказать все в -dealloc
? Если бы вид действительно выгружался, не -dealloc
все равно позвонить?
8 ответов
В дополнение к тому, что уже было указано, я хотел бы подробнее рассказать о логике -viewDidUnload
,
Одна из наиболее важных причин его реализации заключается в том, что UIViewController
Подклассы обычно также содержат ссылки на различные подпредставления в иерархии представлений. Эти свойства могли быть установлены через IBOutlets
при загрузке с кончика или программно изнутри -loadView
, например.
Дополнительное владение подпредставлениями UIViewController
означает, что даже когда его представление удаляется из иерархии представлений и освобождается для экономии памяти, посредством которого подпредставления также высвобождаются представлением, они фактически не будут освобождены, поскольку UIViewController
сам по себе также содержит свои собственные выдающиеся сохраняющие ссылки на эти объекты. Выпуская UIViewController
дополнительное владение этими объектами гарантирует, что они будут также освобождены для освобождения памяти.
Объекты, которые вы отпускаете здесь, обычно воссоздаются и устанавливаются снова, когда UIViewController
вид re-loaded
либо из Nib, либо через реализацию -loadView
,
Также обратите внимание, что UIViewController
view
свойство nil
к тому времени этот метод вызывается.
Как сказано в документации:
Он вызывается в условиях нехватки памяти, когда контроллеру представления необходимо освободить свое представление и любые объекты, связанные с этим представлением, чтобы освободить память.
В той же ситуации dealloc
не называется. Этот метод доступен только в OS3 и выше. Разобраться с той же ситуацией в iPhone OS 2.x было настоящей болью!
Обновление июль 2015: Следует отметить, что viewDidUnload
устарел в iOS 6, потому что "представления больше не удаляются в условиях нехватки памяти, и поэтому этот метод никогда не вызывается". Таким образом, современный совет не беспокоиться об этом и использовать dealloc
,
Это потому, что вы обычно устанавливаете @property
как "(nonatomic, retain)"
и поэтому создатель, созданный для вас, освобождает текущий объект, а затем сохраняет аргумент, т.е.
self.property = nil;
... делает что-то вроде:
[property release];
property = [nil retain];
Поэтому вы убиваете двух зайцев одним выстрелом: управление памятью (освобождение существующего объекта) и присвоение указателя nil (поскольку при отправке любого сообщения нулевому указателю возвращается nil).
Надеюсь, это поможет.
Помни что viewDidUnload
это метод в контроллере представления, а не в представлении. Вид dealloc
метод будет вызван, когда представление выгружается, но контроллер представления dealloc
метод может быть вызван только позже.
Если вы получаете предупреждение о нехватке памяти и ваше представление не отображается, что произойдет, например, примерно каждый раз, когда вы используете UIImagePickerController, чтобы позволить пользователю сделать снимок, ваше представление будет выгружено и после этого потребуется перезагрузить.
Заключение:
Контроллеры представления имеют свойство view. Обычно перо или фрагмент кода добавляет другие представления к этому представлению. Это часто происходит внутри метода -viewDidLoad, например:
- (void)viewDidLoad {
[super viewDidLoad];
[self createManyViewsAndAddThemToSelfDotView];
}
кроме того, файл пера может создать кнопку и добавить ее к представлению контроллера представления.
На iPhone OS 2.2, когда -didReceiveMemoryWarning был вызван из системы, вы должны были выпустить что-то, чтобы освободить память. Вы могли бы освободить представление всего контроллера представления, если это имело смысл. Или просто большое содержание памяти в нем.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
Теперь в новой ОС 3.0 есть метод -viewDidUnload, который будет вызываться из системы, когда представление было выгружено из-за нехватки памяти (пожалуйста, исправьте меня: когда именно это вызывается?)
-viewDidUnload используется для освобождения всех объектов, которые принадлежали как самому контроллеру представления, так и представлению. Причина: если контроллер представления содержит ссылки на дочерние элементы представления, т. Е. Кнопку, ссылочные дочерние представления не будут освобождены, поскольку их счетчик сохранения равен>= 1. После того, как они освобождены в -viewDidUnload, они могут быть освобождены. из памяти.
Apple устарела viewWillUnload, теперь вы должны использовать didReceiveMemoryWarning или dealloc для освобождения ваших объектов.
В iOS 6 методы viewWillUnload и viewDidUnload UIViewController теперь устарели. Если вы использовали эти методы для выпуска данных, используйте вместо этого метод didReceiveMemoryWarning. Вы также можете использовать этот метод для освобождения ссылок на представление контроллера представления, если оно не используется. Вы должны проверить, что представление не в окне, прежде чем сделать это.
Если контроллер представления извлечен из стека навигационных контроллеров и не сохранен где-либо еще, он будет освобожден, и вместо viewDidUnload будет вызван dealloc. Вы должны освободить представления, созданные в loadView в dealloc, но нет необходимости устанавливать переменные равными nil, потому что вскоре после вызова dealloc переменные больше не будут существовать.
Вы можете освободить любые подпредставления, которые вы держите, например, UIImageView, который вы сохранили в вашем методе loadView, или, что еще лучше, изображение, которое было в этом UIImageView.