视图控制器:如何以编程方式在视图之间切换?

简而言之:我想有两个全屏视图,我可以在视图A和视图B之间切换。我知道我可以使用Tab Bar Controller,但我不想。 我想看看这是如何完成的,以了解引擎盖下正在发生的事情。

我有一个UIViewController充当根控制器:

@interface MyRootController : UIViewController { IBOutlet UIView *contentView; } @property(nonatomic, retain) UIView *contentView; @end 

contentView被连接到一个UIView,我把它作为子视图的子视图添加到Nib的“视图”中。 这有绿色,我看到它全屏。 工作正常。

然后,我几乎以同样的方式创build了另外两个视图控制器。 ViewControllerA和ViewControllerB。 ViewControllerA具有蓝色背景,ViewControllerB具有黑色背景。 只要看看哪一个是活跃的。

所以,在myRootController的实现中,我这样做:

 // 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]; } 

顺便说一句,-initWithNib方法看起来像这样:

 - (id)initWithNib { // Load the view nib if (self = [super initWithNibName:@"ViewA" bundle:nil]) { // do ivar initialization here, if needed } return self; } 

这样可行。 当我启动应用程序时,我看到ViewControllerA的视图。 但现在最大的问题是:一个视图控制器通常具有所有这些方法,如:

  • (空隙)viewWillAppear中:(BOOL)animation;
  • (空隙)viewDidDisappear:(BOOL)animation;
  • (无效)viewDidLoad中;

…等等。 谁或什么,或者如果我这样做“我的”没有标签栏控制器的方式将如何调用这些方法? 我的意思是:如果我分配该ViewController的类和视图得到可见,我将不得不注意调用这些方法? 它如何知道viewWillAppear,viewDidDisappear或viewDidLoad? 我相信,标签栏控制器具有所有这一切的“聪明”之下。 还是我错了?

更新:我testing了它。 如果我释放视图控制器(例如:ViewControllerA),我将不会在viewDidDisappear上的日志消息。 只有当分配和初始化ViewControllerA,我得到一个viewDidLoad。 但就是这样。 所以现在所有的迹象都代表了UITabBarController的聪明之处;)我必须弄清楚如何复制它,对吗?

你可以从最简单的removeFromSuperview / insertSubview开始,一点一点地向它添加代码。

 //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]; 

在开始iPhone开发的第6章中有一个切换视图的好例子。 你可以在这里看到它的源代码: http : //iphonedevbook.com/

SwitchViewController有代码以编程方式更改视图。

 - (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]; } 

如果我理解正确,你想要完成的事情是非常简单的。

只需在应用程序委托上添加一个UINavigationController,然后执行:

 [navigationController pushView:vcA]; 

代表们将被相应地调用:

  • (空隙)viewWillAppear中:(BOOL)animation;
  • (空隙)viewDidDisappear:(BOOL)animation;
  • (无效)viewDidLoad中;

而当你想popup视图,推另一个:

 [navigationController popViewControllerAnimated:true]; [navigationController pushView:vcB]; 

如果你不想显示的navigationController只是使用:

 [navigationBar setHidden:YES]; 

其中navigationBar是对应于您的UINavigationController的UINavigationBar。

这可能是一个老问题,但我最近遇到了同样的问题,很难find有效的工作。 我想在两个互补的视图控制器之间切换,但是我希望开关是animation的(内置的animation工作正常),并且我希望它可以与故事板兼容。

为了利用内置的转换,UIView的+transitionFromView:toView:duration:options:completion:方法可以很好地工作。 但是,它只是在视图之间转换,而不是视图控制器。

对于整个视图控制器之间的转换,不仅仅是视图,创build一个自定义UIStoryboardSegue是要走的路。 无论您是否使用故事板,这种方法都可以让您封装整个转换过程,并pipe理从一个视图控制器到下一个视图控制器的相关信息传递。 它只涉及UIStoryboardSegue子类UIStoryboardSegue和重写一个单一的方法, – -perform

有关参考实现,请参阅RAFlipReplaceSegue ,这是我使用这种方法放在一起的准确定制RAFlipReplaceSegue 。 作为一个奖励,它也replace旧的视图控制器与新的,如果它在UINavigationController堆栈。