Acabo de sumergirme por primera vez en el desarrollo de iOS, y una de las primeras cosas que tuve que hacer es implementar un controlador de vista de contenedor personalizado , llamémoslo SideBarViewController
, que intercambia cuál de varios posibles controladores de vista infantil es muestra, casi exactamente como un controlador de barra de pestañas estándar . (Es más o menos un controlador de barra de pestañas pero con un menú lateral que se puede ocultar en lugar de una barra de pestañas).
Según las instrucciones de la documentación de Apple, llamo addChildViewController
cada vez que agrego un ViewController secundario a mi contenedor. Mi código para cambiar el controlador de vista infantil actual se muestra SideBarViewController
así:
- (void)showViewController:(UIViewController *)newViewController {
UIViewController* oldViewController = [self.childViewControllers
objectAtIndex:0];
[oldViewController removeFromParentViewController];
[oldViewController.view removeFromSuperview];
newViewController.view.frame = CGRectMake(
0, 0, self.view.frame.size.width, self.view.frame.size.height
);
[self addChildViewController: newViewController];
[self.view addSubview: newViewController.view];
}
Luego comencé a tratar de averiguar qué addChildViewController
hace aquí, y me di cuenta de que no tenía ni idea. Además de colocar lo nuevo ViewController
en la .childViewControllers
matriz, parece que no tiene ningún efecto en nada. Las acciones y salidas desde la vista del controlador infantil al controlador infantil que configuré en el guión gráfico todavía funcionan bien incluso si nunca llamo addChildViewController
, y no puedo imaginar qué más podría afectar.
De hecho, si reescribo mi código para no llamar addChildViewController
y, en cambio, me veo así ...
- (void)showViewController:(UIViewController *)newViewController {
// Get the current child from a member variable of `SideBarViewController`
UIViewController* oldViewController = currentChildViewController;
[oldViewController.view removeFromSuperview];
newViewController.view.frame = CGRectMake(
0, 0, self.view.frame.size.width, self.view.frame.size.height
);
[self.view addSubview: newViewController.view];
currentChildViewController = newViewController;
}
... entonces mi aplicación todavía funciona perfectamente, ¡hasta donde yo sé!
La documentación de Apple no arroja mucha luz sobre qué lo addChildViewController
hace, o por qué se supone que debemos llamarlo. El alcance completo de la descripción relevante de lo que hace el método o por qué debería usarse en su sección en la UIViewController
Referencia de clase es, en la actualidad:
Agrega el controlador de vista dado como hijo. ... Este método solo está destinado a ser llamado por una implementación de un controlador de vista de contenedor personalizado. Si anula este método, debe llamar a super en su implementación.
También está este párrafo anterior en la misma página:
Su controlador de vista de contenedor debe asociar un controlador de vista secundario consigo mismo antes de agregar la vista raíz del niño a la jerarquía de vistas. Esto permite que iOS enrute correctamente los eventos a los controladores de vista infantil y las vistas que administran esos controladores. Del mismo modo, después de eliminar la vista raíz de un niño de su jerarquía de vistas, debería desconectar ese controlador de vista secundario de sí mismo. Para hacer o deshacer estas asociaciones, su contenedor llama a métodos específicos definidos por la clase base. Estos métodos no están destinados a ser llamados por clientes de su clase de contenedor; solo deben ser utilizados por la implementación de su contenedor para proporcionar el comportamiento de contención esperado.
Estos son los métodos esenciales a los que puede necesitar llamar:
addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:
pero no ofrece ninguna pista sobre cuáles son los 'eventos' o el 'comportamiento de contención esperado' de los que está hablando, o por qué (o incluso cuándo) llamar a estos métodos es 'esencial'.
Todos los ejemplos de controladores de vista de contenedor personalizados en la sección "Controladores de vista de contenedor personalizados" de la documentación de Apple llaman a este método, así que supongo que tiene un propósito importante más allá de simplemente colocar el ViewController secundario en una matriz, pero no puedo entender averiguar cuál es ese propósito. ¿Qué hace este método y por qué debería llamarlo?
fuente
Respuestas:
Yo también me estaba preguntando sobre esta pregunta. Vi la Sesión 102 de los videos de la WWDC 2011 y el Sr. View Controller, Bruce D. Nilo , dijo esto:
Entonces parece que la llamada a
addChildViewController:
hace muy poco. Los efectos secundarios de la llamada son la parte importante. Vienen de las relacionesparentViewController
ychildViewControllers
. Estos son algunos de los efectos secundarios que conozco:transitionFromViewController:toViewController:…
cuando ambos VC necesitan tener el mismo padrenavigationController
,tabBarController
propiedades, etc.fuente
Creo que un ejemplo vale más que mil palabras.
Estaba trabajando en una aplicación de biblioteca y quería mostrar una bonita vista de bloc de notas que aparece cuando el usuario quiere agregar una nota.
Después de probar algunas soluciones, terminé inventando mi propia solución personalizada para mostrar el bloc de notas. Entonces, cuando quiero mostrar el bloc de notas, creo una nueva instancia de
NotepadViewController
y agrego su vista raíz como una subvista a la vista principal. Hasta aquí todo bien.Luego noté que la imagen del bloc de notas está parcialmente oculta debajo del teclado en modo horizontal.
Así que quería cambiar la imagen del bloc de notas y subirla. Y para hacerlo, escribí el código adecuado en el
willAnimateRotationToInterfaceOrientation:duration:
método, ¡pero cuando ejecuté la aplicación no pasó nada! Y después de la depuración, noté que ninguno deUIViewController
los métodos de rotación de 'está realmente llamadoNotepadViewController
. Solo se están llamando a esos métodos en el controlador de vista principal.Para resolver esto, necesitaba llamar a todos los métodos
NotepadViewController
manualmente cuando se llaman en el controlador de vista principal. Esto pronto complicará las cosas y creará una dependencia adicional entre componentes no relacionados en la aplicación.Eso fue en el pasado, antes de que se introdujera el concepto de controladores de vista infantil. Pero ahora, solo necesita acceder
addChildViewController
al controlador de vista principal y todo funcionará como se espera sin más trabajo manual.Editar: hay dos categorías de eventos que se reenvían a los controladores de vista infantil:
1- Métodos de aparición:
2- Métodos de rotación:
También puede controlar qué categorías de eventos desea que se reenvíen automáticamente anulando
shouldAutomaticallyForwardRotationMethods
yshouldAutomaticallyForwardAppearanceMethods
.fuente
addChildViewController
al controlador principal.-[UIViewController addChildViewController:]
solo agrega el controlador de vista pasado en una matriz de viewControllers que un viewController (el padre) quiere mantener la referencia. En realidad, debería agregar esas vistas de viewController en la pantalla usted mismo agregándolas como subvistas de otra vista (por ejemplo, la vista de parentViewController). También hay un objeto de conveniencia en Interface Builder para usar childrenViewControllers en Storyboards.Anteriormente, para mantener la referencia de otros viewControllers de los que usaba las vistas, tenía que mantener la referencia manual de ellos en @properties. Tener una propiedad incorporada como
childViewControllers
y, en consecuencia,parentViewController
es una forma conveniente de administrar tales interacciones y crear viewControllers compuestos como el UISplitViewController que se encuentra en las aplicaciones de iPad.Además, childrenViewControllers también reciben automáticamente todos los eventos del sistema que recibe el padre: -viewWillAppear, -viewWillDisappear, etc. Anteriormente, debería haber llamado a estos métodos manualmente en sus "childrenViewControllers".
Eso es.
fuente
iOS "system events"
no arroja mucho; ¿No parece ser un término que usa Apple?