iOS 6 – viewDidUnload migrate to didReceiveMemoryWarning?

Entonces, con viewDidUnload obsoleto a partir de iOS 6, ¿qué debo hacer ahora?

Eliminarlo, y migrar todos sus contenidos en didReceiveMemoryWarning , o dejarlo, y no hacer nada en didReceiveMemoryWarning ?

La respuesta corta es que, en muchos casos, no necesita cambiar nada. Y, sin duda, no desea simplemente migrar todos los contenidos de viewDidUnload a didReceiveMemoryWarning .

En general, la mayoría de nosotros establece las referencias de IBOutlet a nil en viewDidUnload (en gran parte porque Interface Builder nos lo pone) y realiza la liberación general de memoria (por ejemplo, borrado de cachés, liberación de datos de modelo fácilmente recreables, etc.) en didReceiveMemoryWarning . Si esa es la forma en que lo haces, entonces probablemente no requieras ningún cambio de código.

De acuerdo con la documentación de viewDidUnload de iOS 6:

Las vistas ya no se purgan en condiciones de poca memoria, por lo que este método nunca se llama.

Por lo tanto, no desea mover la configuración de sus referencias de IBOutlet a nil ninguna parte, porque las vistas ya no se purgan. No tendría sentido establecerlos en nil en didReceiveMemoryWarning o algo por el estilo.

Pero, si estuviera respondiendo a eventos de poca memoria liberando objetos de modelo recreados con facilidad, vaciando cachés, etc., en viewDidUnload , eso definitivamente debería pasar a didReceiveMemoryWarning . Pero, de nuevo, la mayoría de nosotros ya lo teníamos allí.

Finalmente, si didReceiveMemoryWarning algo en didReceiveMemoryWarning , solo asegúrate de que tu código no se base en que se viewDidLoad crear en viewDidLoad cuando vuelvas a viewDidLoad , porque no se viewDidLoad (ya que la vista, en sí misma, nunca se descargó).

Como dice applefreak, depende de lo que estuvieras haciendo en viewDidUnload . Si actualiza su pregunta con ejemplos explícitos de lo que tenía en su viewDidUnload , probablemente podamos brindarle consejos menos abstractos.

La respuesta corta:

Nunca utilice -didReceiveMemoryWarning para una eliminación equilibrada, ya que podría llamarse nunca o varias veces. Si tiene su configuración en -viewDidLoad, coloque su código de limpieza en -dealloc.


La respuesta larga:

No es fácil dar una respuesta general, ya que realmente depende de la situación. Sin embargo, hay dos hechos importantes que declarar:

1. -viewDidUnload está en desuso y, de hecho, nunca se llamó a partir de iOS6 y posterior. Por lo tanto, si tiene su código de limpieza allí, su aplicación se filtra bajo estas versiones del sistema operativo

2. -DidReceiveMemoryWarning podría ser llamado varias veces o nunca. Así que es un lugar realmente malo para un desassembly equilibrado de los objetos que creaste en otro lado

Mi respuesta es mirar el caso común donde está usando propiedades, por ejemplo:

 @property (strong) UIView *myCustomView // <-- this is what I'm talking about @property (assign) id *myDelegate 

Aquí debe realizar una limpieza, ya sea porque creó y posee el customView o InterfaceBuilder lo creó, pero lo está reteniendo. Antes de iOS 6 probablemente habrías hecho algo como esto:

 - (void)viewDidLoad { self.myCustomView = [[UIView alloc] initWithFrame:…]; } - (void)viewDidUnload { // <-- deprecated! [myCustomView removeFromSuperView]; self.myCustomView = nil; } 

... porque (de nuevo) myCustomView es una propiedad retenida, creada y de su propiedad, por lo que debe tener cuidado y "liberarla" (configurarla en cero) al final.

Con iOS 6, el mejor lugar para reemplazar -viewDidUnload y establecer la propiedad retenida a cero es probablemente -dealloc . También hay viewWillAppear y viewDidDisappear , pero estos no están vinculados al ciclo de vida de su vista / controlador, pero el ciclo de visualización (por otro lado, los métodos de ... aparecen son perfectos para anular el registro de escuchas de notificación). Por lo tanto, puede que no sea apropiado crear y destruir vistas antes y después de cada pantalla. dealloc es el único método del que podemos estar seguros al final del ciclo de vida del controlador. Tenga en cuenta que no debe llamar a [super dealloc] si está usando ARC:

 - (void)dealloc { self.myCustomView = nil; } 

Sin embargo, si está usando viewDidLoad para hacer alguna configuración relacionada con la vista que puede liberarse en condiciones de poca memoria, las otras publicaciones que muestran cómo lidiar con situaciones de poca memoria son totalmente válidas. En este caso, también puede usar dealloc, pero debe verificar si sus puntos de vista aún están allí.

El ciclo de vida de un ViewController

Tal vez también sea útil buscar el ciclo de vida general de un ViewController:

Esta es la vida útil de un controlador de vista (las líneas en cursiva significan que estos métodos se pueden llamar varias veces) :

  • init: ViewController cargado, no hay elemento de interfaz (IBOutlet) disponible todavía (todo nulo)
  • viewDidLoad: el plumín / guión gráfico se ha cargado y todos los objetos están disponibles. El usuario no ve nada todavía
  • viewWillAppear: la vista está a punto de mostrarse
  • viewDidAppear: la vista está en la pantalla
  • viewWillDisappear: la vista está a punto de desaparecer
  • viewDidDisappear: la vista acaba de salir de la ventana
  • viewDidUnload: NUNCA LLAMADO en iOS6 / 7
  • didReceiveMemoryWarning: no sabe si, cuándo y con qué frecuencia se llama. Antes de iOS6 podría descargar la vista, después de iOS6 simplemente purga una caché fuera de pantalla o no hace nada
  • dealloc: the viewController está a punto de ser destruido

Entonces, para resumir hay varias posibilidades; lo que va donde ahora realmente depende de lo que se inicializó, donde:

  • -dealloc si se creó en -init: o -viewDidLoad:
  • -viewWill / DidDisappear (emparejado con -viewWill / DidAppear)
  • -didReceiveMemoryWarning (se podría o no llamar)

Si necesita saber si su UIViewController está descartando, puede agregar este código a su viewWillDisappear:

 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self isBeingDismissed] || [self isMovingFromParentViewController]) { // Do your viewDidUnload stuff } } 

No se llama al mismo tiempo que viewDidUnload una vez en el ciclo de vida del controlador de vista, ¡pero funciona en la mayoría de los casos para sus necesidades!

Depende de lo que haga en viewDidUnload pero puede usar didReceiveMemoryWarning o dealloc para liberar datos. Mira esto

En la mayoría de los casos, este método se puede usar en lugar de la antigua viewDidUnload.

 // The completion handler, if provided, will be invoked after the dismissed controller's viewDidDisappear: callback is invoked. - (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion NS_AVAILABLE_IOS(5_0); 

Sintaxis de Swift 2017:

 override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { if (yourChildViewController != nil) { print("good thing we did this!") } yourChildViewControllerProperty = nil super.dismiss(animated: flag, completion: completion) }