ios storyboard segue viewdidload

ios - viewDidLoad llamado antes de que prepareForSegue termine



storyboard (4)

Tenía la impresión de que viewDidLoad se llamará DESPUÉS de que prepareForSegue finalice Así es como Hegarty enseña su clase de Stanford (tan recientemente como febrero de 2013).

Sin embargo, por primera vez hoy, he notado que viewDidLoad se llamaba ANTES de que prepareForSegue se completara. Por lo tanto, las propiedades que estaba configurando en prepareForSegue no estaban disponibles para el destinationViewController dentro del método viewDidLoad de los destinos.

Esto parece contrario al comportamiento esperado.

ACTUALIZAR

Me acabo de dar cuenta de lo que estaba pasando. En mi destinationViewController tenía un configurador personalizado que volvería a cargar el tableView cada vez que se actualizaba el "modelo":

DestinationViewController - (void)setManagedObjectsArray:(NSArray *)managedObjectsArray { _managedObjectsArray = [managedObjectsArray copy]; [self.tableView reloadData]; }

Resulta que, dado que destinationViewController es una subclase de UITableViewController ... llamar a ''self.tableView'' hace que la vista se cargue. De acuerdo con la documentación de Apple, llamar a la propiedad de vista de un controlador de vista puede hacer que la vista se cargue. La vista de un UITableViewController es el tableView.

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

Por lo tanto, en prepareForSegue la siguiente línea forzaba la vista del destinationViewController para cargar:

vc.managedObjectsArray = <custom method that returns an array>;

Para solucionar el problema, cambié el configurador personalizado del modelo destinationViewController a:

- (void)setManagedObjectsArray:(NSArray *)managedObjectsArray { _managedObjectsArray = [managedObjectsArray copy]; if ([self isViewLoaded]) { [self.tableView reloadData]; } }

Esto solo volverá a cargar el tableView si el tableView está en la pantalla. Por lo tanto, no obliga a cargar la vista durante prepareForSegue.

Si alguien se opone a este proceso, por favor comparta sus pensamientos. De lo contrario, espero que esto evite una larga noche de insomnio para alguien.


Gracias por compartir, me ayudó a resolver mi problema.

En mi caso, destinationViewController es un UITabBarController y la modificación de viewControllers Array activó viewDidLoad:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UITabBarController *tabBarController = segue.destinationViewController; tabBarController.viewControllers = ... tabBarController.something = something; }

en el viewDidLoad necesitaba el atributo algo para ser configurado, así que tuve que moverlo hacia arriba:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UITabBarController *tabBarController = segue.destinationViewController; tabBarController.something = something; tabBarController.viewControllers = ... }


Me había topado con confusiones similares en el pasado. Las reglas generales que aprendí son:

  1. Se llama a prepareForSegue antes de viewDidLoad de VC de destino
  2. viewDidLoad se llama solo después de que TODAS las salidas están cargadas
  3. No intente hacer referencia a ningún punto de venta de VC de destino en prepareForSegue de VC de origen.

Otra lección aprendida con respecto a prepareForSegue es evitar el procesamiento redundante. Por ejemplo, si ya seguras una celda tableView a un VC a través del guión gráfico, podrías tener una condición de carrera similar si intentas procesar BOTH tableView: didSelectRowAtIndexPath y prepareForSegue. Uno puede evitar esto mediante la utilización manual o renunciar a cualquier procesamiento en didSelectRowAtIndexPath.


Pensé que añadiría una pequeña explicación sobre lo que sucedió aquí:

Se llama a prepareForSegue antes de que se muestre la vista

viewDidload se llama la primera vez que se accede a la vista.

Lo que probablemente sucedió es que accedió a la view en prepareForSegue activando la vista cargando manualmente.

Normalmente el flujo es:

  1. preformSegue
  2. prepareForSegue
  3. ViewController se agrega a la jerarquía
  4. viewDidLoad .

Pero lo que probablemente sucedió en tu caso es:

  1. preformSegue
  2. prepareForSegue
  3. | - En prepareForSegue accedes a la view
  4. | - view se carga automáticamente => viewDidLoad se invoca
  5. Regreso desde performSegue
  6. ViewController se agrega a la jerarquía, sin viewDidLoad (ya llamado)

Por lo tanto, sí, normalmente no se accede a la propiedad de view antes de agregar ViewController a la jerarquía, pero si lo está, viewDidLoad se puede activar antes.


la solución simple es colocar

[self.tableView reloadData];

A la vista, viewWillAppear :