ios cocoa-touch memory-management uiview uiviewcontroller

ios - UIViewController evita que la vista se descargue



cocoa-touch memory-management (5)

¿Podría ser tan simple?

Aunque en ninguna parte de la documentación se menciona esto, parece que si conservo exclusivamente mi vista en viewDidLoad, entonces no se publica en Advertencia de memoria. Intenté con varias advertencias consecutivas en el simulador y todas siguen pareciendo buenas.

Entonces ... el truco por el momento es "retener" en viewDidLoad, y una versión en dealloc: de esta manera, el controlador de vista está "atascado" con la vista hasta el momento en que se debe liberar.

Voy a probar un poco más, y escribiré sobre los resultados.

Cuando la aplicación de mi iPhone recibe una advertencia de memoria, las vistas de UIViewControllers que no están visibles actualmente se descargan. En un controlador en particular, descargar la vista y las salidas es bastante fatal.

Estoy buscando una manera de evitar que esta vista se descargue. Considero que este comportamiento es bastante estúpido. Tengo un mecanismo de caché, así que cuando llega una advertencia de memoria, me descargo toneladas de datos y libero suficiente memoria, pero definitivamente necesito esta vista sin tocar.

Veo que UIViewController tiene un método unloadViewIfReloadable , que se llama cuando llega la advertencia de memoria. ¿Alguien sabe cómo decirle a Cocoa Touch que mi vista no es recargable?

¿Alguna otra sugerencia sobre cómo evitar que se descargue mi vista en la advertencia de memoria?

Gracias por adelantado

Apple docsea sobre el ciclo de vida de la vista de un controlador de vista dice:

didReceiveMemoryWarning: la implementación predeterminada libera la vista solo si determina que es seguro hacerlo

Ahora ... sobrescribo didReceiveMemoryWarning con una función vacía que simplemente llama a NSLog para avisarme que se recibió una advertencia. Sin embargo, la vista se descarga de todos modos. Además, en qué criterios se decide exactamente si una vista es segura para descargar ... ¡oh! ¡Muchas preguntas!


Debido a que la solución aceptada tiene problemas con viewDidUnload sigue llamando aunque la vista se bloqueó para que no se borrara, estoy usando un enfoque diferente aunque aún frágil. El sistema descarga la vista mediante un mensaje unloadViewForced: al controlador, por lo que estoy interceptando eso para bloquear el mensaje. Esto evita la llamada confusa a viewDidUnload . Aquí está el código:

@interface UIViewController (Private) - (void)unloadViewForced:(BOOL)forced; @end - (void)unloadViewForced:(BOOL)forced { if (!_safeToUnloadView) { return; } [super unloadViewForced:forced]; }

Esto tiene problemas obvios, ya que está interceptando un mensaje no documentado en UIViewController.

progrmr publicó una respuesta anterior que recomienda interceptar didReceiveMemoryWarning en didReceiveMemoryWarning lugar. Basado en los rastros de pila que he visto, la intercepción también debería funcionar. Sin embargo, no he intentado esa ruta porque me preocupa que pueda haber otra limpieza de la memoria que también se bloquee (por ejemplo, al no llamar a los controladores de vista secundarios con el mensaje de advertencia de la memoria).


Lo que parece funcionar para mí fue anular setView: ignorar la configuración en nil. Es una tontería, pero entonces, este es un problema grave, y esto hizo el truco:

-(void)setView:(UIView*)view { if(view != nil || self.okayToUnloadView) { [super setView:view]; } }


No creo que ninguna de estas ideas funcione. Intenté anular [didReceiveMemoryWarning], y funcionó en algunos teléfonos, pero encontré que un teléfono descargó la vista ANTES de que se haya llamado a ese método (debe haber estado en una memoria extremadamente baja o algo así). La anulación de [setView] produce un montón de advertencias de registro, por lo que no me arriesgaría a que Apple lo haga. Al retener la vista solo se filtrará esa vista (evitará bloqueos pero no funcionará realmente), la vista se reemplazará la próxima vez que se cargue la interfaz de usuario de los controladores.

Así que realmente solo tienes que planear que tus vistas se descarguen cada vez que estén fuera de la pantalla, lo cual no es lo ideal, pero listo. Los mejores patrones que he encontrado para trabajar con esto son el compromiso inmediato, por lo que su UI siempre está actualizada, o copia-edición-copia, donde copia su modelo en una instancia temporal, completa sus vistas y utiliza el compromiso inmediato con esa instancia, luego copie los cambios a su modelo original cuando el usuario haga clic en "guardar" o lo que sea.


Según los documentos, la implementación predeterminada de didReceiveMemoryWarning: libera la vista si es seguro hacerlo (es decir: superview == nil).

Para evitar que se publique la vista, puede anular didReceiveMemoryWarning: pero en su implementación no llame a [super didReceiveMemoryWarning] . Ahí es donde se publica la vista de forma predeterminada (si no está visible).

El valor predeterminado didReceiveMemoryWarning libera la vista llamando a [viewcontroller setView:nil] , por lo que podría anularla en su lugar.