ios - una - vistas necesarias dibujo tecnico
Intercambio de vistas secundarias en una vista de contenedor (3)
Cuando tiene vistas secundarias que tienen sus propios controladores de vista, debe seguir el patrón de controlador de contenedor personalizado. Consulte Creación de controladores de vista de contenedor personalizados para obtener más información.
Suponiendo que haya seguido el patrón de contenedor personalizado, cuando desee cambiar el controlador de vista secundaria (y su vista asociada) para la "vista de contenido", lo haría mediante programación con algo como:
UIViewController *newController = ... // instantiate new controller however you want
UIViewController *oldController = ... // grab the existing controller for the current "content view"; perhaps you maintain this in your own ivar; perhaps you just look this up in self.childViewControllers
newController.view.frame = oldController.view.frame;
[oldController willMoveToParentViewController:nil];
[self addChildViewController:newController]; // incidentally, this does the `willMoveToParentViewController` for the new controller for you
[self transitionFromViewController:oldController
toViewController:newController
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
// no further animations required
}
completion:^(BOOL finished) {
[oldController removeFromParentViewController]; // incidentally, this does the `didMoveToParentViewController` for the old controller for you
[newController didMoveToParentViewController:self];
}];
Cuando lo hace de esta manera, no hay necesidad de ninguna interfaz de protocolo de delegado con el controlador de la vista de contenido (que no sea lo que iOS ya proporciona con los Controladores de vista secundarios en un método de Contenedor personalizado ).
Por cierto, esto supone que el controlador secundario inicial asociado con esa vista de contenido se agregó así:
UIViewController *childController = ... // instantiate the content view''s controller any way you want
[self addChildViewController:childController];
childController.view.frame = ... // set the frame any way you want
[self.view addSubview:childController.view];
[childController didMoveToParentViewController:self];
Si desea que un controlador secundario le diga al padre que cambie el controlador asociado con la vista de contenido, usted:
Definir un protocolo para esto:
@protocol ContainerParent <NSObject> - (void)changeContentTo:(UIViewController *)controller; @end
Defina el controlador principal para cumplir con este protocolo, por ejemplo:
#import <UIKit/UIKit.h> #import "ContainerParent.h" @interface ViewController : UIViewController <ContainerParent> @end
Implemente el método
changeContentTo
en el controlador principal (como se describe anteriormente):- (void)changeContentTo:(UIViewController *)controller { UIViewController *newController = controller; UIViewController *oldController = ... // grab reference of current child from `self.childViewControllers or from some property where you stored it newController.view.frame = oldController.view.frame; [oldController willMoveToParentViewController:nil]; [self addChildViewController:newController]; [self transitionFromViewController:oldController toViewController:newController duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ // no further animations required } completion:^(BOOL finished) { [oldController removeFromParentViewController]; [newController didMoveToParentViewController:self]; }]; }
Y los controladores secundarios ahora pueden usar este protocolo en referencia a la propiedad
self.parentViewController
que iOS proporciona para usted:- (IBAction)didTouchUpInsideButton:(id)sender { id <ContainerParent> parentViewController = (id)self.parentViewController; NSAssert([parentViewController respondsToSelector:@selector(changeContentTo:)], @"Parent must conform to ContainerParent protocol"); UIViewController *newChild = ... // instantiate the new child controller any way you want [parentViewController changeContentTo:newChild]; }
Deje que ContainerView
sea la vista principal del contenedor con dos vistas de contenido secundario: NavigationView
y ContentView
.
Me gustaría poder cambiar el controlador de ContentView
con otra vista. Por ejemplo, intercambiando un controlador de página de inicio con un controlador de página de noticias. Actualmente, la única forma en que puedo pensar para hacer esto es usar un delegado para decirle a ContainerView
que quiero cambiar de vista. Esto parece una manera descuidada de hacer esto porque ContainerViewController
terminaría teniendo un grupo de delegados especiales para todas las subvistas.
Esto también necesita comunicarse con NavigationView
que tiene información sobre qué vista se encuentra actualmente en ContentView
. Por ejemplo: si el usuario está en la página de noticias, la barra de navegación dentro de la vista de navegación mostrará que el botón de noticias está actualmente seleccionado.
Pregunta A: ¿Hay alguna forma de cambiar el controlador en ContentView
sin un método de delegado llamando al propio ContainerView
? Me gustaría hacer esto programáticamente (sin guiones gráficos).
Pregunta B: ¿Cómo puedo cambiar los controladores en ContentView
desde NavigationView
sin una llamada de delegado? Me gustaría hacer esto programáticamente (sin guiones gráficos).
Para ese tipo de transición también puede usar UIView.animateWith...
animations.
Por ejemplo, supongamos que rootContainerView
es contenedor y contentViewController
controlador activo actualmente en contenedor, luego
func setContentViewController(contentViewController:UIViewController, animated:Bool = true) {
if animated == true {
addChildViewController(contentViewController)
contentViewController.view.alpha = 0
contentViewController.view.frame = rootContainerView.bounds
rootContainerView.addSubview(contentViewController.view)
self.contentViewController?.willMoveToParentViewController(nil)
UIView.animateWithDuration(0.3, animations: {
contentViewController.view.alpha = 1
}, completion: { (_) in
contentViewController.didMoveToParentViewController(self)
self.contentViewController?.view.removeFromSuperview()
self.contentViewController?.didMoveToParentViewController(nil)
self.contentViewController?.removeFromParentViewController()
self.contentViewController = contentViewController
})
} else {
cleanUpChildControllerIfPossible()
contentViewController.view.frame = rootContainerView.bounds
addChildViewController(contentViewController)
rootContainerView.addSubview(contentViewController.view)
contentViewController.didMoveToParentViewController(self)
self.contentViewController = contentViewController
}
}
// MARK: - Private
private func cleanUpChildControllerIfPossible() {
if let childController = contentViewController {
childController.willMoveToParentViewController(nil)
childController.view.removeFromSuperview()
childController.removeFromParentViewController()
}
}
esto le proporcionará animaciones de fade simples, también puede probar cualquier UIViewAnimationOptions
, transiciones, etc.
Parece que te estás confundiendo. Un contentView (suponiendo que UIView
) no ''contiene'' un controlador que cambiaría. Un UIViewController
maneja su UIView. Me parece que necesita una configuración de controlador de vista padre-hijo.
Un controlador de vista padre único, que manejaría los controles de vista secundarios, cada uno de los cuales puede manejar cuando se muestra cada uno en la pantalla y ajustar su UIViews y el contenido en consecuencia. Por favor, consulte la documentación de Apple a continuación.