views:

9701

answers:

3

In short: I want to have two fullscreen views, where I can switch between view A and view B. I know I could just use an Tab Bar Controller, but I dont want to. I want to see how this is done by hand, for learning what's going on under the hood.

I have an UIViewController that acts as an root controller:

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

@end

the contentView is hooked up to an UIView which I added as an subview to the "view" of the Nib. This has green color and I see it fullscreen. Works fine.

Then, I created two other View Controllers pretty 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;
}

That works. I see the view from ViewControllerA when I start the app. But now the big question is: A View Controller typically has all those methods like:

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

...and so on. Who or what, or how would those methods be called if I do it "my" way without a tab bar controller? I mean: If I allocate that ViewController's class and the view get's visible, would I have to take care about calling those methods? How does it know that viewWillAppear, viewDidDisappear, or viewDidLoad? I believe that the Tab Bar Controller has all this "cleverness" under the hood. Or am I wrong?

UPDATE: I've tested it. If I release the view controller (for example: ViewControllerA), I will get no log message on viewDidDisappear. Only when allocating and initializing the ViewControllerA, I get an viewDidLoad. But that's it. So all signs stand for the cleverness of UITabBarController now ;) and I have to figure out how to replicate that, right?

+5  A: 

If I understand correctly, what you are trying to accomplish is pretty straightforward.

Just add a UINavigationController on your application delegate and do:

[navigationController pushView:vcA];

Delegates will be called accordingly:

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

And when you want to pop the view and push another one:

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

If you don't want the navigationController showing just use:

[navigationBar setHidden:YES];

Where navigationBar is the UINavigationBar corresponding to your UINavigationController.

Pablo Santa Cruz
sounds good but I dont want any kind of navigation or tab bar ;) I just want naked views with a button "go to B", and on the other "go to A". Or is there a way of not having that navigation bar above?
Thanks
You can definitely hide the navigation bar if you don't want it showing on the screen. I will update the answer with the info.
Pablo Santa Cruz
+5  A: 

There's a nice example of switching views in Chapter 6 of Beginning iPhone Development. You can see the source code for it here: http://iphonedevbook.com/

SwitchViewController has the code to change views programatically.


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

}
nevan
+9  A: 

You can begin from the simplest removeFromSuperview/insertSubview and add code to it little by little.


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

iPhoney