Using Multiple ViewControllers on a Single Screen in iOS

In the world of iOS we usually stick with a single ViewController per screen. In fact, this is so common that many developers are not even aware that it’s possible to use more than one ViewController on a single screen. I’m going to run through a quick example and then highlight some of the benefits and gotchas of using multiple ViewControllers.

Example

As an example I’m going to create a separate ViewController that manages a custom navigation bar – this might be something that you want to be to add to any screen in your application.

I started off by creating a Single-View Application in XCode – this will give me a single ViewController and a single xib for that ViewController. Nothing new so far.

Now let’s create the ViewController for the navigation bar – I named it NavBarViewController. I chose to use a xib with the ViewController, but you could also do everything in code.

Custom Navigation Bar

As you can see I added a single button to the view – simply to illustrate that we can handle actions within NavBarViewController. In the initialization code for the NavBarViewController I specify that this xib should be used.

@implementation NavBarViewController

- (id)init
{
    return [super initWithNibName:@"NavBarViewController" bundle:nil];
}

@end

Now we can go ahead and add the NavBarViewController to the main screen.

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.navBarViewController = [[NavBarViewController alloc] init];
    self.navBarViewController.view.frame = CGRectMake(0, 0, 320, 75);
    
    [self addChildViewController:self.navBarViewController];
    [self.view addSubview:self.navBarViewController.view];
}

@end

The key here is that you need to set the frame of the child ViewController in the parent – if you try and set the frame in the child ViewController itself you will see some weirdness due to being in the wrong coordinate system.

Lastly I added an action to the main ViewController that simply toggles the navigation bar being shown. I also added some animation so that the navigation bar appears to slide into view.

- (IBAction)toggleNavBar:(UIButton *)sender
{
    CGRect newFrame;
    if (self.isNavBarVisible)
        newFrame = CGRectMake(0, -75, 320, 75);
    else
        newFrame = CGRectMake(0, 0, 320, 75);
    
    [UIView animateWithDuration:0.3f animations:^{
        self.navBarViewController.view.frame = newFrame;
    }];
    
    self.isNavBarVisible = !self.isNavBarVisible;
}

Multiple ViewControllers

That’s all there is to it.

Why use Multiple ViewControllers

The ability to extract functionality into separate ViewControllers is very powerful – in this case we would be able to reuse the navigation bar on any screen in our application with minimal code duplication. You also get full access to the view lifecycle (ViewDidLoad, ViewDidAppear, etc) within your child ViewController.

I have found that using multiple ViewControllers leads to better abstractions, clear separation of concerns and overall cleaner code.

You can find my full example on GitHub. Happy coding.