2009-08-17 13 views
45

Nota: Esta pregunta es outdated- viewDidUnload iOS está en desuso 6.¿Cuándo se llama a UIViewController viewDidUnload?

Cuando no viewDidUnload de forma automática UIViewController ser llamado? Sí, lo sé, cuando la vista se descarga. ¿Pero cuándo sucede eso automáticamente? ¿Cómo puedo hacerlo manualmente? Gracias.

+4

Parece que no se llama necesariamente; un UIViewController puede desasignarse sin llamar primero a viewDidUnload. – beetstra

+0

Después de una extensa prueba, definitivamente veo que viewDidUnload NO se puede llamar a veces. Veo que los controladores de vista se desasignan sin que se llame a viewDidUnload. –

+0

Esta pregunta debe ser eliminada. viewDidUnload está en desuso y ya no se llama en iOS 6. –

Respuesta

42

Si emite una advertencia de memoria en el simulador (consulte el menú), se llamará a cualquier controlador de vista conectado a una vista que no esté visible.

Esto se debe a que los controladores de vista están registrados por defecto para notificaciones de advertencia de memoria, y cualquier vista que no esté siendo utilizada actualmente será descargada por el controlador de vista - el método viewDidUnload está ahí para que pueda limpiar todo lo que desee , para ahorrar memoria extra (o si ha conservado algunos IBOutlets para ayudar a liberar memoria que de lo contrario se liberaría al descargar la vista).

En general, cualquier IBOutlet que libere en dealloc, también debe ser liberado (y las referencias establecidas en nil) en este método.

+0

No se llamará para mi aplicación porque solo tengo un controlador de vista instanciado a la vez, cuando los cambio primero desasoco (self.vc = nil) el actual (después de eliminarlo de la supervista). – mk12

+0

No uso IBOutlet, no uso IB. – mk12

+0

Estoy bastante seguro de que tiene razón, si solo tiene un VC a la vez, la vista nunca se descargará. El caso más común es cuando usa un controlador de navegación, y las vistas desde las que navegó aún están allí ... Incluso si no usa IB, si agrega las subvistas que conserva las referencias, se aplicaría la misma regla: anule la referencia (aunque, una vez más, esto parece no aplicarse en su caso). –

17

-viewDidUnload se invoca cada vez que la propiedad viewViewtroller's view se establece en nil, ya sea manualmente o más comúnmente a través de didReceiveMemoryWarning:.

+0

Tengo un escenario en el que quiero -viewDidUnload disparar en mi UIViewController que fue alojado por un UIPopoverController. Después de que se haya eliminado el popover, estoy anulando manualmente la vista del controlador de vista, pero -viewDidUnload todavía no se ha activado. ¿Alguna idea de por qué no? – dreyln

+0

¿Pusiste un punto de interrupción en viewDidUnload para confirmar que no se está disparando? Asegúrese de que su código que establece que la vista sea nula en realidad haga referencia al controlador de vista correcto (compruebe que el controlador de vista no sea nulo en ese momento, y que su valor sea el mismo que el esperado). La causa más común de este tipo de problemas es, accidentalmente, un controlador de vista extra que no está en la pantalla. –

+0

Sí, tuve un punto de interrupción y un código que invalida un temporizador. El punto de interrupción nunca se golpeó y mi temporizador siguió funcionando (fue registrar mensajes en la consola). También verifiqué que contentViewController de mi popover era correcto y no nulo. Me pregunto si la vista sigue siendo técnicamente visible. Estoy anulando la vista en el método -popoverControllerDidDismissPopover :. – dreyln

37

Además de emitir manualmente una memoria de advertencia en el simulador, puede emitir una programáticamente con

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

A continuación, puede hacer que esto suceda cada 5 segundos usando un temporizador

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

animado Idea brillante para probar una aplicación. – Guillaume

+0

Esta es una gran idea, aunque como esto solo se usaría para las pruebas, probablemente sería mejor usar el método privado en UIApplication que se llama cuando ocurre una advertencia de memoria real, en caso de que haga algo más: '[[ UIApplication sharedApplication] performSelector: @selector (_performMemoryWarning)]; ' –

3

viewDidUnload llamado en condiciones de poca memoria. Deberíamos descargar cosas que cargamos en el método viewDidLoad. Tenemos que renunciar a la propiedad del objeto llamando al método de acceso para establecerlo en cero. En el caso de una salida, el objeto se libera por sí mismo para que la referencia del objeto se pueda establecer de manera segura en nil. Si no es una propiedad sintetizada, entonces primero tenemos que liberar el objeto de lo que establecemos en cero.

9

iOS 6.x y más tarde

Sé que esto es una cuestión más viejo, pero me siento una respuesta debe ser presentada en relación con los cambios en la API viewDidUnload en iOS 6 a saber, que en iOS 6 viewDidUnload hay más tiempo llamado (en absoluto) y ha sido desaprobado.

+2

Además de esto: si implementas contra iOS 5 aún deberías escribir una implementación' viewDidUnload', pero es vital no tener ninguna lógica que necesite ejecutarse en iOS 6 allí. – mxcl

Cuestiones relacionadas