iphone - create - viewcontroller ionic
didReceiveMemoryWarning, viewDidUnload y dealloc (4)
didReceiveMemoryWarning
...
Acción: libere todo lo que no necesite, es probable que esté deshaciendo lo que pudo haber configurado en viewDidLoad.
Esto está mal. Todo lo que viewDidLoad
crear en viewDidLoad
debe publicarse (y establecerse en nil
) en viewDidUnload
. Como mencionas a continuación, didReceiveMemoryWarning
también se llama cuando la vista está visible. En didReceiveMemoryWarning
, debe liberar elementos como cachés u otros controladores de vista que está guardando para que se puedan recrear perezosamente la próxima vez que se requieran (es decir, implementando su getter manualmente).
viewDidUnload
...
Acción: en general, cualquier IBOutlets que libere en dealloc, también debe ser liberado (y las referencias deben establecerse en cero) en este método. Tenga en cuenta que si las propiedades se configuran para retenerlas, entonces establecerlas en nil también las liberará.
Correcto. En general, todo lo que crea en viewDidLoad y todos los IBOutlets que se declaran como retain
deben publicarse y establecerse en nil
aquí.
Dealloc
...
Acción: libere todos los objetos que han sido retenidos por la clase, incluidos, entre otros, todas las propiedades con retener o copiar.
Correcto. Vale la pena señalar que esto incluye todos los objetos que maneja en viewDidUnload
porque este último no se llama implícitamente en el proceso de dealloc
(AFAIK, no del todo seguro). Es por eso que es esencial establecer todos los objetos de lanzamiento en nil
en viewDidUnload
porque de lo contrario, se arriesga a soltar algo dos veces (primero en viewDidUnload
y luego nuevamente en dealloc
; si establece el puntero en nil
, la llamada de lanzamiento en dealloc
no tendrá efecto).
Controladores de vista emergente y memoria
Pregunta 2: ¿Al abrir una vista, se elimina de la memoria?
No necesariamente. Ese es un detalle de implementación que no debería preocuparle. Cualquiera que sea la práctica actual, Apple podría cambiarla en la próxima versión.
He revisado muchas publicaciones, mis libros y el Desarrollador de Apple y he recogido la mayor parte de la comprensión que necesito sobre el uso de estos. Estaría muy agradecido si alguna persona amable pudiera confirmar que lo he entendido bien (o corregirme) y también responder las dos preguntas.
Muchas gracias,
Chris
Orden de los mensajes En general, los mensajes aparecerán en el siguiente orden:
didReceiveMemoryWarning
viewDidUnload (que puede ser causado por 1), obviamente solo se aplica a las clases de controlador de vista.
Dealloc
didReceiveMemoryWarning
Se llama cuando el sistema tiene poca memoria.
De forma predeterminada, los controladores de vista están registrados para las notificaciones de advertencia de memoria y, dentro del método de plantilla, la llamada a [super didReceiveMemoryWarning] libera la vista si no tiene una vista de supervisión, que es una forma de verificar si la vista es visible o no. Libera la vista estableciendo su propiedad en nil.
Acción: libere todo lo que no necesite, es probable que deshaga lo que haya configurado en viewDidLoad. No libere elementos de la interfaz de usuario, ya que estos deberían ser publicados por viewDidUnload.
Pregunta 1: parece que esto se llamará incluso si la vista es visible, por lo que es difícil ver lo que se puede liberar de forma segura. Sería muy útil entender esto y algunos ejemplos de lo que podría ser publicado.
viewDidUnload
Se llama cuando una propiedad de vista del controlador de vista no visible se establece en nulo, ya sea de forma manual o más comúnmente a través de didReceiveMemoryWarning.
El método viewDidUnload está allí para que pueda: - limpiar cualquier otra cosa que desee, para ahorrar memoria extra o - si ha conservado algunos IBOutlets, para ayudar a liberar memoria que de otro modo no se liberaría al descargar la vista .
Acción: en general, cualquier IBOutlets que libere en dealloc, también debe ser liberado (y las referencias deben establecerse en cero) en este método. Tenga en cuenta que si las propiedades se configuran para retenerlas, entonces establecerlas en nil también las liberará.
Dealloc
Se invoca cuando el objeto del controlador de vista se desasigna, que será cuando el recuento de retención caiga a cero.
Acción: libere todos los objetos que han sido retenidos por la clase, incluidos, entre otros, todas las propiedades con retener o copiar.
Controladores de vista emergente y memoria
Pregunta 2: ¿Al abrir una vista, se elimina de la memoria?
A partir de iOS 6, cómo podemos comprobar si la vista se ha cargado de nuevo. Dado que "viewDidUnload" está en desuso. ¿Está seguro de que "loadView" y "viewDidload" llamarán si la vista se está eliminando después de la advertencia "didReceiveMemoryWarning"?
Algunas correcciones y sugerencias:
-
didReceiveMemoryWarning
prácticas
Como ha dicho, la implementación predeterminada del controlador didReceiveMemoryWarning
publica su vista si es "seguro hacerlo". Si bien no está claro en los documentos de Apple lo que significa "seguro hacerlo", generalmente se reconoce que no tiene supervisión (por lo tanto, no hay forma de que la vista esté actualmente visible), y su método loadView
puede reconstruir la vista completa sin problemas. .
La mejor práctica cuando reemplaza didReceiveMemoryWarning
es no intentar liberar ningún objeto de vista. Solo libere sus datos personalizados, si ya no es necesario. Con respecto a las vistas, simplemente deje que la implementación de la superclase se ocupe de ellas.
A veces, sin embargo, la necesidad de los datos puede depender del estado de su vista. En la mayoría de los casos, esos datos personalizados se configuran en el método viewDidLoad
. En estos casos, ''seguro para liberar datos personalizados'' significa que sabe que loadView
y viewDidLoad
se invocarán antes de que el controlador de vista vuelva a utilizar los datos personalizados.
Por lo tanto, en su didReceiveMemoryWarning
, llame primero a la implementación de la superclase, y si se descarga su vista, entonces libere los datos personalizados porque sabe que se invocarán de nuevo loadView
y viewDidLoad
. Por ejemplo,
- (void)didReceiveMemoryWarning {
/* This is the view controller''s method */
[super didReceiveMemoryWarning];
if (![self isViewLoaded]) {
/* release your custom data which will be rebuilt in loadView or viewDidLoad */
}
}
Tenga cuidado de no usar self.view == nil
, porque self.view
asume que la vista es necesaria para alguien e inmediatamente la cargará de nuevo.
- método
viewDidUnload
Se llama a viewDidUnload
cuando el controlador de vista descargó la vista debido a una advertencia de memoria . Por ejemplo, si elimina la vista de la vista de supervisión y configura la propiedad de view
del controlador en nil
, no se invocará el método viewDidUnload
. Un punto sutil es que incluso si la vista de un controlador de vista ya se publicó y se establece en nulo en el momento en que el controlador recibe didReceiveMemoryWarning
, por lo que en realidad no hay una vista para descargar para el controlador, se invocará viewDidUnload
si llama a la implementación de la superclase de didReceiveMemoryWarning
.
Por eso no es una buena práctica establecer manualmente la propiedad view
de un controlador de vista en nil. Si lo hace, también puede enviar un mensaje viewDidUnload
. Supongo que su comprensión de viewDidUnload
es más deseable, pero aparentemente no es el comportamiento actual.
- Controladores de vista emergente
Si quiere decir ''eliminar de la vista de supervisión'' por ''hacer estallar'', disminuye el recuento de retención de la vista, pero no necesariamente la desasigna.
Si quiere decir que está saliendo de un UINavigationController, en realidad disminuye el conteo de retención del propio controlador de vista. Si el controlador de vista no es retenido por otro objeto, será desasignado, deseablemente con su vista. Como expliqué, viewDidUnload
no se invocará esta vez.
- Otros...
Técnicamente, la cuenta de retención no puede bajar a cero. Es más probable que el objeto se desasigne sin establecer el recuento en cero de antemano.
Solo para asegurarse, el controlador de vista en sí no suele ser desasignado por comportamientos predeterminados debido a la advertencia de memoria.
Solo para actualizar este hilo para que sea relevante para iOS6:
viewDidUnload y viewWillUnload quedaron obsoletos en iOS6. Estos métodos nunca se llaman.
Para este y otros métodos en desuso, consulte: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html