View controllers: how to programmatically switch between views?

In short: I want to have two full-screen views where I can switch between view A and view B. I know that I can just use the tab bar controller, but I don't want that. I want to see how this is done manually to find out what is happening under the hood.

I have a UIViewController that acts as a root controller:

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

ContentView connects to the UIView, which I added as a view to the Nib "view". It is green and I see it in full screen. It works great.

Then I created two other View Controllers in much the same way. ViewControllerA and ViewControllerB. ViewControllerA has a blue background, ViewControllerB has a black background. Just to see which one is active.

So, in the implementation of myRootController, I do this:

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

By the way, the -initWithNib method looks like this:

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

It works. I see the ViewControllerA view when the application starts. But now the big question is: A View Controller usually has all such methods as:

  • (voids) viewWillAppear: (BOOL) animated;
  • (voids) viewDidDisappear: (BOOL) animated;
  • (voids) viewDidLoad;

... and so on. Who or what, or how will these methods be called if I make it my way without a tab bar controller? I mean: if I highlighted this ViewController class and the view became visible, would I need to take care of calling these methods? How does he know that viewWillAppear, viewDidDisappear or viewDidLoad? I believe that the Tab Bar Controller has all this “skill” under the hood. Or am I wrong?

UPDATE: I tested it. If I release the view controller (for example: ViewControllerA), I will not receive the log message in viewDidDisappear. Only when distributing and initializing ViewControllerA do I get viewDidLoad. But it is so. So, all the signs mean UITabBarController smart now;) and I need to figure out how to do this, right?

+52
iphone uikit uiviewcontroller uitabbarcontroller
May 26 '09 at 2:30 p.m.
source share
4 answers

You can start with the simplest removeFromSuperview / insertSubview and add some code to it.

 //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]; 
+39
May 26 '09 at 3:18 p.m.
source share

A good example of switching views is in Chapter 6, “Starting iPhone Development.” Here you can see the source code: http://iphonedevbook.com/

SwitchViewController has code for changing views programmatically.

 - (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]; } 
+50
May 26 '09 at 14:54
source share

If I understand correctly, what you are trying to do is pretty simple.

Just add the UINavigationController to your application delegate and do:

 [navigationController pushView:vcA]; 

Delegates will be called accordingly:

  • (voids) viewWillAppear: (BOOL) animated;
  • (voids) viewDidDisappear: (BOOL) animated;
  • (voids) viewDidLoad;

And when you want to set the view and click another one:

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

If you do not want the navigation controller to show only usage:

 [navigationBar setHidden:YES]; 

If the navigationBar is a UINavigationBar corresponding to your UINavigationController.

+21
May 26 '09 at 2:40 p.m.
source share

This might be an old problem, but I recently ran into the same problem and had difficulty finding something that worked. I wanted to switch between two additional view controllers, but I wanted the switch to be animated (the built-in animation worked fine), and I wanted it to be compatible with downstream versions, if possible.

To use the built-in transition, the UIView +transitionFromView:toView:duration:options:completion: method works beautifully. But this is just a transition between views, not a view of controllers.

To navigate between entire view controllers, not just views, creating a custom UIStoryboardSegue is the way to go. Regardless of whether you use storyboards, this approach allows you to encapsulate the entire transition and manage the transfer of relevant information from one view controller to another. It includes only a subclass of UIStoryboardSegue and an override of one method, -perform .

For a reference implementation, see RAFlipReplaceSegue , the exact user segment I compiled using this approach. As a bonus, it also replaces the old view controller with the new one if it is on the UINavigationController stack.

+2
Dec 15
source share



All Articles