iphone - tarjetas - programar etiquetas nfc
Controladores de vista: ¿cómo cambiar entre vistas mediante programación? (4)
Este puede ser un problema antiguo, pero recientemente me encontré con el mismo problema y tuve dificultades para encontrar algo que funcionara. Quería cambiar entre dos controladores de vista complementarios, pero quería que el interruptor se animara (las animaciones integradas funcionan bien), y quería que fuera compatible con los guiones gráficos, si era posible.
Para aprovechar la transición incorporada, el método UIView +transitionFromView:toView:duration:options:completion:
funciona muy bien. Pero, solo transiciones entre vistas, no ver controladores.
Para que la transición se UIStoryboardSegue
entre los controladores de vista completa, no solo las vistas, la creación de una UIStoryboardSegue
personalizada es el camino a seguir. Independientemente de que use storyboards, este enfoque le permite encapsular toda la transición y administrar el paso de información relevante de un controlador de vista a otro. Solo implica subclasificar UIStoryboardSegue
y anular un único método, -perform
.
Para una implementación de referencia, vea RAFlipReplaceSegue
, la RAFlipReplaceSegue
personalizada exacta que RAFlipReplaceSegue
usando este enfoque. Como UINavigationController
adicional, también reemplaza el controlador de vista anterior por el nuevo si está en una pila UINavigationController
.
En resumen: quiero tener dos vistas de pantalla completa, donde pueda cambiar entre la vista A y la vista B. Sé que podría usar un controlador de barra de pestañas, pero no quiero. Quiero ver cómo se hace esto a mano, para aprender lo que sucede bajo el capó.
Tengo un UIViewController que actúa como controlador raíz:
@interface MyRootController : UIViewController {
IBOutlet UIView *contentView;
}
@property(nonatomic, retain) UIView *contentView;
@end
ContentView está conectado a un UIView que agregué como una subvista a la "vista" del Nib. Esto tiene color verde y lo veo a pantalla completa. Funciona bien.
Luego, creé otros dos Controladores de Vista más o menos de la misma manera. ViewControllerA y ViewControllerB. ViewControllerA tiene un fondo azul, ViewControllerB tiene un fondo negro. Solo para ver cuál está activo.
Entonces, en la implementación de myRootController, hago esto:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
ViewControllerA *vcA = [[ViewControllerA alloc] initWithNib];
[self.contentView addSubview:vcA.view];
[cvA release];
}
Por cierto, el método -initWithNib tiene este aspecto:
- (id)initWithNib { // Load the view nib
if (self = [super initWithNibName:@"ViewA" bundle:nil]) {
// do ivar initialization here, if needed
}
return self;
}
Eso funciona. Veo la vista desde ViewControllerA cuando inicio la aplicación. Pero ahora la gran pregunta es: un controlador de vista generalmente tiene todos esos métodos, como:
- (void) viewWillAppear: (BOOL) animado;
- (void) viewDidDisappear: (BOOL) animado;
- (void) viewDidLoad;
...y así. ¿Quién o qué o cómo se llamarían esos métodos si lo hago "a mi manera" sin un controlador de barra de pestañas? Quiero decir: si asignase esa clase de ViewController y la vista get visible, ¿debería tener cuidado de llamar a esos métodos? ¿Cómo sabe que viewWillAppear, viewDidDisappear, o viewDidLoad? Creo que el controlador Tab Bar tiene toda esta "inteligencia" bajo el capó. ¿O estoy equivocado?
ACTUALIZACIÓN: lo he probado. Si lanzo el controlador de vista (por ejemplo: ViewControllerA), no obtendré ningún mensaje de registro en viewDidDisappear. Solo al asignar e inicializar ViewControllerA, obtengo un viewDidLoad. Pero eso es todo. Entonces, todas las señales representan la inteligencia de UITabBarController ahora;) y tengo que descubrir cómo replicar eso, ¿verdad?
Hay un buen ejemplo de cambio de vistas en el Capítulo 6 de Beginning iPhone Development. Puede ver el código fuente aquí: http://iphonedevbook.com/
SwitchViewController tiene el código para cambiar vistas de forma programática.
- (IBAction)switchViews:(id)sender
{
if (self.yellowViewController == nil)
{
YellowViewController *yellowController = [[YellowViewController alloc]
initWithNibName:@"YellowView" bundle:nil];
self.yellowViewController = yellowController;
[yellowController release];
}
[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
if (self.blueViewController.view.superview == nil)
{
coming = blueViewController;
going = yellowViewController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else
{
coming = yellowViewController;
going = blueViewController;
transition = UIViewAnimationTransitionFlipFromRight;
}
[UIView setAnimationTransition: transition forView:self.view cache:YES];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[going.view removeFromSuperview];
[self.view insertSubview: coming.view atIndex:0];
[going viewDidDisappear:YES];
[coming viewDidAppear:YES];
[UIView commitAnimations];
}
Puede comenzar desde el más simple removeFromSuperview / insertSubview y agregarle código poco a poco.
//SwitchViewController.h
#import
@class BlueViewController;
@class YellowViewController;
@interface SwitchViewController : UIViewController {
IBOutlet BlueViewController *blueViewController;
IBOutlet YellowViewController *yellowViewController;
}
- (IBAction)switchViews:(id)sender;
@property (nonatomic, retain) BlueViewController *blueViewController;
@property (nonatomic, retain) YellowViewController *yellowViewController;
@end
//1. remove yellow view and insert blue view
- (IBAction)switchViews:(id)sender {
if(self.blueViewController.view.superview == nil)
{
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:blueViewController.view atIndex:0];
}
}
//2. appear=insert, disappear=remove
if(blueViewController.view.superview == nil)
{
[blueViewController viewWillAppear:YES];
[yellowViewController viewWillDisappear:YES];
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:self.blueViewController.view atIndex:0];
[yellowViewController viewDidDisappear:YES];
[blueViewController viewDidAppear:YES];
}
//3. now add animation
[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
//blue view will appear by flipping from right
if(blueViewController.view.superview == nil)
{
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight
forView:self.view cache:YES];
[blueViewController viewWillAppear:YES];
[yellowViewController viewWillDisappear:YES];
[yellowViewController.view removeFromSuperview];
[self.view insertSubview:self.blueViewController.view atIndex:0];
[yellowViewController viewDidDisappear:YES];
[blueViewController viewDidAppear:YES];
}
[UIView commitAnimations];
Si entiendo correctamente, lo que estás tratando de lograr es bastante sencillo.
Simplemente agregue un UINavigationController en su delegado de aplicación y haga lo siguiente:
[navigationController pushView:vcA];
Los delegados serán llamados en consecuencia:
- (void) viewWillAppear: (BOOL) animado;
- (void) viewDidDisappear: (BOOL) animado;
- (void) viewDidLoad;
Y cuando quieras abrir la vista y presionar otra:
[navigationController popViewControllerAnimated:true];
[navigationController pushView:vcB];
Si no quiere que se muestre el control de navegación simplemente use:
[navigationBar setHidden:YES];
Donde navigationBar es la UINavigationBar correspondiente a su UINavigationController.