viewDidLoad de hecho se llama cada vez que hay una transición segue

He visto muchas publicaciones en el desbordamiento de stack que indican que el método viewDidLoad de controlleres solo se llama la primera vez que se accede al controller y no necesariamente siempre, pero siempre al less una vez.

¡Esto no es lo que estoy viendo en absoluto! Hice una testing simple para resaltar esto: https://github.com/imuz/ViewDidLoadTest

Parece que para las segues del controller de navigation y las vistas modal se llama siempre a LoadDid. La única vez que no se llama es cuando se cambia entre tabs.

Toda explicación de viewDidLoad que puedo encontrar contradice esto:

  • ¿Cuándo se llama a viewDidLoad?
  • UIViewController viewDidLoad vs. viewWillAppear: ¿Cuál es la split adecuada del trabajo?
  • http://www.manning-sandbox.com/thread.jspa?threadID=41506

Y la propia documentation de las manzanas indica que una vista solo se descarga cuando la memory es baja.

Actualmente estoy haciendo la initialization en viewDidLoad haciendo la suposition de que se llama con cada transición segue.

¿Me estoy perdiendo de algo?

Creo que la documentation de Apple describe una situación en la que el controller de vista no está siendo desasignado. Si usa un segue, está causando la instanciación de un nuevo controller de destino y, al ser un object nuevo, necesita cargar una vista.

En las aplicaciones basadas en xib, a veces he almacenado en caching un object de controller que sabía que podría volver a usar con frecuencia. En esos casos, se comportaron de acuerdo con la documentation en términos de cuándo se tuvo que cargar una vista.

Editar: Al leer los enlaces que incluyó, no veo ninguna contradicción en ellos. Ellos también están hablando de cosas que suceden durante la vida útil de un object controller de vista.

La respuesta de Phillip Mills es correcta. Esto es solo una mejora de él.

El sistema funciona como está documentado.

Está viendo viewDidLoad porque el controller de vista que se está presionando en el controller de navigation es una nueva instancia. Debe llamar a viewDidLoad.

Si investigas un poco más, verás que cada uno de esos controlleres de vista se desasigna cuando se reventan (simplemente pon un punto de interrupción o NSLog en dealloc). Esta desasignación no tiene nada que ver con el contenedor del controller de vista … no controla la vida del controller que usa … solo tiene una fuerte reference al mismo.

Cuando el controller se desconecta de la stack del controller de navigation, el controller de navigation libera su reference y, dado que no hay otras references a él, el controller de vista eliminará.

El controller de navigation solo contiene references fuertes para ver los controlleres que se encuentran en su stack activa.

Si desea reutilizar el mismo controller, usted es responsable de reutilizarlo. Cuando usas segues storyboard, renuncias a ese control (en gran medida).

Digamos que tiene una opción de push para ver el controller Foo como resultado de tocar un button. Cuando se toca ese button, "el sistema" creará una instancia de Foo (el controller de vista de destino) y luego ejecutará la segue. El contenedor del controller ahora tiene la única reference fuerte a ese controller de vista. Una vez que se hace con él, el VC se desasignará.

Dado que crea un nuevo controller cada vez, se viewDidLoad a viewDidLoad cada vez que se presente el controller.

Ahora, si desea cambiar este comportamiento y almacenar en caching el controller de vista para su posterior reutilización, debe hacerlo específicamente. Si no usa segues de storyboard, es fácil ya que está empujando / haciendo estallar el VC al controller de nav.

Sin embargo, si usa segues de storyboard, es un poco más de problemas.

Hay varias forms de hacerlo, pero todos requieren algún tipo de piratería. El storyboard en sí mismo está a cargo de crear instancias de nuevos controlleres de vista. Una forma es anular instantiateViewControllerWithIdentifier . Ese es el método que se llama cuando un segue necesita crear un controller de vista. Se le llama incluso a los controlleres a los que no le da un identificador (el sistema proporciona un identificador único confeccionado si no asigna uno).

Tenga en count que espero que esto sea principalmente para fines educativos. Ciertamente, no estoy sugiriendo esto como la mejor manera de resolver sus problemas, sea lo que sea que sean.

Algo como…

 @interface MyStoryboard : UIStoryboard @property BOOL shouldUseCache; - (void)evict:(NSString*)identifier; - (void)purge; @end @implementation MyStoryboard - (NSMutableDictionary*)cache { static char const kCacheKey[1]; NSMutableDictionary *cache = objc_getAssociatedObject(self, kCacheKey); if (nil == cache) { cache = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, kCacheKey, cache, OBJC_ASSOCIATION_RETAIN); } return cache; } - (void)evict:(NSString *)identifier { [[self cache] removeObjectForKey:identifier]; } - (void)purge { [[self cache] removeAllObjects]; } - (id)instantiateViewControllerWithIdentifier:(NSString *)identifier { if (!self.shouldUseCache) { return [super instantiateViewControllerWithIdentifier:identifier]; } NSMutableDictionary *cache = [self cache]; id result = [cache objectForKey:identifier]; if (result) return result; result = [super instantiateViewControllerWithIdentifier:identifier]; [cache setObject:result forKey:identifier]; return result; } @end 

Ahora, debes usar este storyboard. Desafortunadamente, mientras UIApplication se aferra al guión gráfico principal, no expone una API para getla. Sin embargo, cada controller de vista tiene un método, storyboard para get el guión gráfico desde el que se creó.

Si está cargando sus propios storyboards, simplemente instale MyStoryboard. Si está utilizando el guión gráfico pnetworkingeterminado, debe forzar al sistema a que use su guión especial. Una vez más, hay muchas maneras de hacer esto. Una forma sencilla es anular el método accessor de storyboard en el controller de vista.

Puede hacer que MyStoryboard sea una class de proxy que reenvíe todo a UIStoryboard, o puede cambiar el guión gráfico principal, o puede hacer que su controller local devuelva uno de su método de guión gráfico.

Ahora, recuerden, hay un problema aquí. ¿Qué pasa si presiona el mismo controller de vista en la stack más de una vez? Con un caching, el mismo object del controller de vista se usará varias veces. ¿Es eso realmente lo que quieres?

De lo contrario, ahora necesita gestionar la interacción con los contenedores del controller para que puedan comprobar si este controller ya es conocido por ellos, en cuyo caso es necesaria una nueva instancia.

Por lo tanto, hay una manera de get controlleres almacenados en caching mientras usa los segues pnetworkingeterminados del guión gráfico (en realidad hay bastantes maneras) … pero eso no es necesariamente algo bueno, y ciertamente no es lo que obtienes por defecto.

Se llama cada vez que la vista del controller se carga desde cero (es decir, solicitada pero aún no disponible). Si desasigna el controller y la vista lo acompaña, se volverá a llamar la próxima vez que instile el controller (por ejemplo, cuando cree el controller para impulsarlo de manera modal o mediante segue). Los controlleres de vista en tabs no se desasignan porque el controller de tabs los mantiene cerca.