Когда я должен освобождать объекты в - (void) viewDidUnload, а не в -dealloc? - PullRequest
103 голосов
/ 21 июля 2009

Для чего нужен -(void)viewDidUnload?

Могу ли я не просто рассказать все в -dealloc? Если представление все-таки загрузилось, разве -dealloc не будет вызвано?

Ответы [ 8 ]

51 голосов
/ 21 июля 2009

В дополнение к тому, что уже было указано, я хотел бы подробнее рассказать о логике, стоящей за -viewDidUnload.

Одна из наиболее важных причин его реализации заключается в том, что подклассы UIViewController обычно также содержат ссылки на различные подпредставления в иерархии представлений. Эти свойства могли быть установлены через IBOutlets при загрузке с кончика или программно, например, внутри -loadView.

Дополнительное владение подпредставлениями UIViewController означает, что даже когда его представление удаляется из иерархии представлений и освобождается для экономии памяти, посредством которого подпредставления также освобождаются представлением, они фактически не будут освобождены, поскольку UIViewController сам по-прежнему содержит свои собственные выдающиеся сохраняющие ссылки на эти объекты. Освобождение UIViewController дополнительного владения этими объектами гарантирует, что они также будут освобождены для освобождения памяти.

Объекты, которые вы отпускаете здесь, обычно воссоздаются и устанавливаются снова, когда представление UIViewController имеет значение re-loaded, либо из Nib, либо через реализацию -loadView.

Также обратите внимание, что свойство UIViewController view к моменту вызова этого метода равно nil.

21 голосов
/ 21 июля 2009

Как сказано в документации :

Он вызывается в условиях нехватки памяти, когда контроллеру представления необходимо освободить свое представление и любые объекты, связанные с этим представлением, чтобы освободить память.

В той же ситуации dealloc вызывается , а не . Этот метод доступен только в OS3 и выше. Иметь дело с такой же ситуацией в iPhone OS 2.x было настоящей болью!

Обновление за июль 2015 года : следует отметить, что * iOS 1016 устарела в iOS 6, поскольку «представления больше не удаляются в условиях нехватки памяти, поэтому этот метод никогда не вызывается» Итак, современный совет - не переживать об этом и использовать dealloc.

9 голосов
/ 16 июля 2010

Это потому, что вы обычно устанавливаете @property как "(nonatomic, retain)", и поэтому создатель, созданный для вас, освобождает текущий объект, а затем сохраняет аргумент, т.е.

self.property = nil;

... делает что-то вроде:

[property release];
property = [nil retain];

Поэтому вы убиваете двух зайцев одним выстрелом: управление памятью (освобождение существующего объекта) и назначение указателя на ноль (поскольку отправка любого сообщения на указатель ноль возвращает ноль).

Надеюсь, это поможет.

8 голосов
/ 21 июля 2009

Помните, что viewDidUnload - это метод в контроллере представления, а не в представлении. Метод dealloc представления будет вызываться при его выгрузке, но метод dealloc контроллера представления может быть вызван только позже.

Если вы получаете предупреждение о нехватке памяти и ваше представление не отображается, что произойдет, например, примерно каждый раз, когда вы используете UIImagePickerController, чтобы позволить пользователю сделать снимок, ваше представление будет выгружено и его нужно будет перезагрузить после что.

6 голосов
/ 19 декабря 2012

Apple устарела viewWillUnload, теперь вы должны использовать didReceiveMemoryWarning или dealloc для освобождения ваших объектов.

В iOS 6 методы viewWillUnload и viewDidUnload UIViewController теперь устарела. Если вы использовали эти методы чтобы освободить данные, используйте метод didReceiveMemoryWarning. Вы также можно использовать этот метод для освобождения ссылок на представление вид контроллера, если он не используется. Вы должны проверить это вид не в окне, прежде чем делать это.

6 голосов
/ 21 июля 2009

Вывод:

View Controllers имеют свойство 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, они могут быть освобождены по памяти.

5 голосов
/ 09 августа 2010

Если контроллер представления извлекается из стека навигационных контроллеров и не сохраняется где-либо еще, он будет освобожден, и вместо viewDidUnload будет вызван dealloc. Вы должны освободить представления, созданные в loadView в dealloc, но нет необходимости устанавливать переменные равными nil, потому что вскоре после вызова dealloc переменные больше не будут существовать.

3 голосов
/ 21 июля 2009

Вы можете освободить любые подпредставления, к которым вы привязаны, например, UIImageView, который вы сохранили в вашем методе loadView, или, что еще лучше, изображение, которое было в этом UIImageView.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...