UITabBarController inside a UINavigationController

I was recently working on an iPhone application with a client who wanted the application to largely function as a tab bar application, but required displaying several non-tabbed navigation-based screens when the app first loads. For the visually inclined, it looks more or less like this:

It is possible to push non-tabbed views on top of a tab-bar controller with a couple lines of code:

// Create the UIViewController
MyViewController * viewController = [[MyViewController alloc] init];
// Hide the tab bar
viewController.hidesBottomBarWhenPushed = YES;
// Push onto the view stack
[[self navigationController] pushViewController:viewController animated:YES];

However, the opposite is not true; it is not possible to push a tabbed view on top of a non-tabbed view since UINavigationController does not allow UITabBarControllers to be pushed onto its navigation stack. There are a number of workarounds, but in general they seemed a bit hacky to me. The tab bar widget itself can be included on navigation screens, and so one approach is to use the navigation-based application template and to write a custom implementation for the tabbed-based screens. This was apparently the approach that the popular Tweetie app took.

I didn’t like this approach for a couple reasons. First, within each of the tabs, I needed a navigation hierarchy. The programmatic tab bar works ok for simple navigation, but I felt like it would get pretty dicey as things got more complicated. Second, I like to use Interface Builder to visually change layouts as much as possible. I find that it tends to be simpler than hunting things down in code. The programmatic approach means doing a lot of wiring in code that could otherwise be done in IB.

So, perhaps a more elegant solution is to base your application off of the “Tab Bar Application” template and to utilize modal screens where necessary. You can get the effect of having a screen beneath the tab bar controller by displaying a modal screen in applicationDidFinishLaunching:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the tab bar controller's view to the window and display.
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
 
// Create the main screen
MainScreenViewController * mainScreen = [[MainScreenViewController alloc] initWithNibName:@"MainScreen"
bundle:[NSBundle mainBundle]];
// Present as a modal dialog to start the application
[tabBarController presentModalViewController:mainScreen animated:NO];
return YES;
}

If you like, the main screen can even have it’s own navigation stack:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the tab bar controller's view to the window and display.
[window addSubview:tabBarController.view];
[window makeKeyAndVisible]
 
// Create the main screen
MainScreenViewController * mainScreen = [[MainScreenViewController alloc] initWithNibName:@"MainScreen"
bundle:[NSBundle mainBundle]];
 
// Create the nav controller for the main screen
mainScreenNavigationController = [[UINavigationController alloc] initWithRootViewController:titleScreen];
[mainScreen release];
 
// Present as a modal dialog to start the application
[tabBarController presentModalViewController:mainScreenNavigationController animated:NO];
return YES;
}

It’s simple, it’s clean, and it gives you all the advantages of being able to use the tab bar template. Enjoy :).

2 Comments

  1. Reply

    [...] someone show me some code that applies apple view? link i got this web i dont know hot to follow it as im new with [...]

  2. Reply
    stephen January 3, 2012

    cud u post the source code.that could be really helpful

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>