Выпустить в viewDidUnload и dealloc как?

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

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

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

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


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

@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

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

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

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