2011-12-05 25 views
103

En la sesión 102 de WWDC 2011, Apple introdujo la Contención del controlador de vista, que es la capacidad de crear contenedores de controlador de vista personalizados, análogos a UITabBarController, UINavigationController, y similares.¿Cómo funciona la contención de View Controller en iOS 5?

He visto los ejemplos varias veces. Hay una ráfaga de métodos asociados con este patrón, pero fue un poco difícil de resolver exactamente. Voy a publicar aquí lo que creo que está sucediendo y ver si la comunidad confirmará o confirmará mis sospechas.

Escenario 1: Pasar de ningún padre a un nuevo controlador de vista padre

[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

hacer las dos primeras líneas tienen que ocurrir en el orden dado, o pueden ser invertidos?

Escenario 2: Pasar de un controlador de vista padre a ningún controlador de vista padre

[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 

¿Es también necesario llamar [vc didMoveToParentViewController:nil]? Los ejemplos en la sesión 102 no hicieron esto en este escenario, pero no sé si fue una omisión o no.

Escenario 3: Pasar de controlador de vista un padre a otro

Esto probablemente se producirá en la siguiente manera, porque se encapsula la lógica en cada controlador de vista padre.

// In the old parent 
[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 

// In the new parent 
[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; 
[vc didMoveToParentViewController:self]; 

Preguntas

Mi pregunta principal es la siguiente: ¿Es así como vista del controlador de contención debe trabajar, en general? ¿Son correctos los mecanismos anteriores?

¿Es necesario llamar al willMoveToParentViewController antes de llamar al addChildViewController? Esto me parece el orden lógico, pero ¿es estrictamente necesario?

¿Es necesario llamar al didMoveToParentViewController:nil después de llamar al removeFromParentViewController?

+9

El problema fue que cuando traté de añadir la etiqueta IOS5, me golpeó accidentalmente entrar, lo que sumado al poste a pesar de que yo no había terminado de componer/editarlo. Intenté eliminarlo, pero luego descubrí que solo podía * votar * para eliminarlo. –

Respuesta

71

Los documentos UIViewController son bastante claros sobre cuándo y cuándo no llamar a los métodos willMove/didMove. Consulte la documentación "Implementing a Container View Controller".

Los documentos dicen que, si no anulas addChildViewController, no tienes que llamar al método willMoveToParentViewController:. Sin embargo, debe llamar al método didMoveToParentViewController: una vez completada la transición. "Del mismo modo, es responsabilidad del controlador de vista de contenedor llamar al método willMoveToParentViewController: antes de llamar al método removeFromParentViewController. El método removeFromParentViewController llama al método didMoveToParentViewController: del controlador de vista secundaria."

Además, hay un ejemplo resuelto here y código de muestra here.

buena suerte

+15

Veo, por lo que 'addChildViewController' se debe equilibrar con' didMoveToParentViewController' y 'willMoveToParentViewController' se debe equilibrar con' removeFromParentViewController'. Esto es exactamente lo que estaba buscando. No estoy seguro de cómo me lo perdí en los documentos. –

+0

¿Por qué no? ¿Por qué no tiene que llamar a willMoveToParentViewController pero debe llamar a didMoveToParentViewController? –

+0

Porque eso es lo que dicen los documentos. Apple obviamente siente que no necesitamos saber. –

21

Esta parte no es correcto:

[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

According to the docs:

Cuando el contenedor personalizado llama a la addChildViewController: método, se llama automáticamente al willMoveToParentViewController: método de la vista controlador que se agregará como un niño antes de agregarlo.

Así que no necesita la llamada [vc willMoveToParentViewController:self]. Se realiza automáticamente cuando llamas al [self addChildViewController:vc]. Aquí está el ejemplo de código de nuevo:

[self addChildViewController:vc]; 
// [vc willMoveToParentViewController:self] called automatically 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

For removing view controllers:

El método removeFromParentViewController llama automáticamente al didMoveToParentViewController: método del controlador de vista del niño después de que se elimina el niño.

Probablemente esta llamada es [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 
// [vc didMoveToParentViewController:nil] called automatically 
+0

parece que si se hace lo contrario, incluso si parece funcionar, la presentación de ViewController no está configurada en el ViewViewController presentado. – Adrian

+0

Los documentos dicen call 'didMoveToParentViewController'" ** inmediatamente ** después de llamar al addChildViewController: method ", no especifica cuándo realmente se agrega la subvista secundaria. Me pregunto si todos han entendido esto mal. ¿Hay algún ejemplo en algunos Apple Docs con los que podamos comparar esto? – Robert

+0

Nota: * debe * llamar a 'willMoveToParentViewController' antes de' addChildViewController' si el elemento que está moviendo es una clase personalizada con 'addChildViewController' reemplazado (a menos que su sobrescritura lo llame internamente) – bunkerdive

Cuestiones relacionadas