Выпуск в viewDidUnload и dealloc как? - PullRequest
14 голосов
/ 01 марта 2010

Некоторое время я предполагал, что viewDidUnload всегда вызывается, когда контроллер освобождается. Это правильное предположение?

Я только что исследовал некоторые странные вещи и установил точку останова в viewDidUnload моего контроллера, и это dealloc. Похоже, что dealloc вызывается, но метод viewDidUnload никогда не вызывается. Я даже добавил self.view = nil к своему dealloc, и он все еще не вызывал его.

Означает ли это, что сохраненные объекты вида, которые я высвобождаю в методе viewDidUnload, также должны быть освобождены в моем методе dealloc, чтобы убедиться, что они действительно исчезли?

Я знаю, что в StackOverflow есть много других вопросов, касающихся viewDidUnload, но ни один из них не посвящен конкретно проблеме дублирования операторов релиза между двумя методами.


Более конкретный пример в новом проекте SDK 3.1.2:

@implementation TestViewController

@synthesize label;

- (IBAction)push {
    TestViewController *controller = [[[TestViewController alloc] initWithNibName:@"TestViewController" bundle:nil] autorelease];
    [self.navigationController pushViewController:controller animated:YES];
}

- (void)viewDidUnload {
    self.label = nil;
    NSLog(@"viewDidUnload was called");
}

- (void)dealloc {
    [super dealloc];
    NSLog(@"label retain count: %i", [label retainCount]);
}

@end

Мой делегат приложения создает простой контроллер навигации с одним из них в качестве корневого контроллера. Когда я нажимаю кнопку, связанную с push 3 раза, а затем нажимаю кнопку "Назад" три раза, генерируется следующий вывод.

ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2

Что на 2 выше, чем я думаю. Сохраняется один раз для просмотра и один раз для контроллера. Но после dealloc я бы ожидал, что представление исчезнет, ​​освободив мою метку, и контроллер исчезнет, ​​вызвав viewDidUnload и выпустив его. Хотя там может быть autorelease, сбрасывающий счет в этот момент.

Но, по крайней мере, ясно, что viewDidUnload вообще не вызывается, что противоречит этому ответу: Всегда ли viewDidUnload и dealloc вызывались при разрыве UIViewController?

Возможно, мне следует просто вызвать [self viewDidUnload] во всех моих методах dealloc на контроллерах? Хуже, чем может случиться, это то, что я дважды установил свойство nil, верно?

1 Ответ

20 голосов
/ 01 марта 2010

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

Если вам нужно освободить их где-либо еще, всегда устанавливайте ссылку на ноль после release. Это защитит ваше приложение от взрыва позже (вероятно, в dealloc).

Обратите внимание, что в документации совершенно явно говорится, что свойство view уже будет равно nil при вызове viewDidUnload.

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