2009-08-17 4 views
45

Примечание: Этот вопрос outdated- viewDidUnload устарела IOS 6.Когда называется UIViewController viewDidUnload?

Когда viewDidUnload UIViewController автоматически дозвонились? Да, я знаю, когда просмотр выгружается. Но когда это происходит автоматически? Как я могу сделать это вручную? Благодарю.

+4

Похоже, что это не обязательно вызвано; UIViewController может быть освобожден без первого вызова viewDidUnload. – beetstra

+0

После обширного тестирования я определенно вижу, что viewDidUnload иногда НЕ может быть вызван. Я вижу, что контроллеры просмотра получают dealloc'd без вызова viewDidUnload. –

+0

Этот вопрос необходимо удалить. viewDidUnload устарел и больше не вызывается в iOS 6. –

ответ

42

Если вы выдаете предупреждение о предупреждении памяти в симуляторе (смотрите в меню), это вызовет вызов для любого контроллера вида, прикрепленного к виду, которое не отображается.

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

Как правило, любые IBOutlets, которые вы выпускаете в dealloc, также должны быть освобождены (и ссылки установлены на ноль) в этом методе.

+0

Он не будет вызван для моего приложения, потому что у меня только один экземпляр контроллера создается одновременно, когда я сначала переключаю их, я освобождаю (self.vc = nil) текущий (после удаления из супервизора). – mk12

+0

Я не использую IBOutlets, я не использую IB. – mk12

+0

Я уверен, что вы правы, если у вас только один VC за раз, то представление никогда не будет выгружено. Наиболее распространенный случай - когда вы используете навигационный контроллер, а просмотры, которые вы перемещаете, все еще там ... Даже если вы не используете IB, если вы добавите subviews, в котором будут храниться ссылки для одного и того же правила, примените нулевую ссылку (хотя это опять же не применимо в вашем случае). –

17

-viewDidUnload вызывается всякий раз, когда свойство вида viewcontroller установлено равным nil, либо вручную, либо чаще всего через didReceiveMemoryWarning:.

+0

У меня есть сценарий, когда я хочу -viewDidUnload запускать мой UIViewController, который был размещен UIPopoverController. После того, как popover был уволен, я вручную игнорирую представление контроллера вида, но -viewDidUnload все еще не уволен. Любые идеи, почему бы и нет? – dreyln

+0

Вы поставили контрольную точку в viewDidUnload, чтобы подтвердить, что она не стреляет? Убедитесь, что ваш код, который устанавливает представление в нуль, фактически ссылается на правильный контроллер представления (убедитесь, что контроллер представления не сам по себе ниль в этой точке и его значение совпадает с ожидаемым значением). Наиболее распространенной причиной таких проблем является случайный дополнительный контроллер просмотра, который отсутствует на экране. –

+0

Да, у меня была точка останова и некоторый код, который делает недействительным таймер. Точка останова никогда не ударялась, и мой таймер продолжал идти (записывал сообщения на консоль). Я также подтвердил, что contentViewController моего popover был правильным, а не nil. Удивительно, если вид по-прежнему технически виден. Я игнорирую представление в методе -popoverControllerDidDismissPopover:. – dreyln

37

Кроме того, чтобы вручную выдавать память предупреждения в тренажере, вы можете оформить один программно с

- (void)_simulateLowMemoryWarning { 
    // Send out MemoryWarningNotification 
    [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification 
                 object:[UIApplication sharedApplication]]; 
    // Manually call applicationDidReceiveMemoryWarning 
    [[[UIApplication sharedApplication] delegate] applicationDidReceiveMemoryWarning:[UIApplication sharedApplication]]; 
} 

Вы можете вызвать это произойдет через каждые 5 секунд с помощью таймера

static NSTimer *gLowMemoryTimer = nil; 

- (void)stopLowMemoryTimer { 
    [gLowMemoryTimer invalidate]; 
    gLowMemoryTimer = nil; 
} 

- (void)startLowMemoryTimer { 
    if (gLowMemoryTimer) { 
    [self _stopLowMemoryTimer]; 
    } 
    gLowMemoryTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(_simulateLowMemoryWarning) userInfo:nil repeats:YES]; 
} 
+6

Блестящая идея протестировать приложение. – Guillaume

+0

Это отличная идея, хотя, поскольку это будет использоваться только для тестирования, вероятно, было бы лучше использовать частный метод в UIApplication, который вызывается при возникновении реального предупреждения о памяти, на всякий случай, если он сделает что-нибудь еще: '[[ UIApplication sharedApplication] performSelector: @selector (_performMemoryWarning)]; ' –

3

viewDidUnload вызванных в условиях низкой памяти. Мы должны выгрузить материал, который мы загрузили в методе viewDidLoad. Нам нужно отказаться от права собственности на объект, вызвав метод доступа, чтобы установить его на нуль. В случае выхода, объект освобождается, поэтому ссылка на объект может быть безопасно установлена ​​на нуль. Если не синтезированное свойство, то сначала нужно освободить объект, чем мы установили в nil.

9

IOS 6.x и более поздние

Я знаю, что это старая проблема, но я чувствую, ответ должен быть представлен в отношении изменений в viewDidUnload API в IOS 6, а именно, что в IOS 6 viewDidUnload НИКАКОГО более длинный (вообще) и устарел.

+2

Далее: при развертывании с iOS 5 вы все равно должны писать реализацию' viewDidUnload', но очень важно не иметь никакой логики, которая должна была бы запускаться на iOS 6. – mxcl