Having a UITabBar AND a UINavigationController in an app?

10,936

Solution 1

Just wrap the view controller inside the UINavigationController and Place the UINavigationController inside the UITabBar. This will work fine for you…

Example:

NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:2];

tabBarController = [[UITabBarController alloc] init];
[tabBarController setDelegate:self];

UINavigationController *navigationController = nil;
navigationController = [[UINavigationController alloc] initWithRootViewController:<Your View controller1>];
[tabBarViewControllers addObject:navigationController];
[navigationController release];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:<Your View controller2>];
[tabBarViewControllers addObject:navigationController];
[navigationController release];
navigationController = nil;

tabBarController = tabBarViewControllers;
[tabBarViewControllers release];
tabBarViewControllers = nil;

Solution 2

Use the wizard for a Tab Bar Application, and set it up as normal. In any tab where you want to add a navigation controller, create it in the XIB using the library. My XIB has:

- File's Owner          DescriptiveNameNavViewController
- First Responder
- View                  UIVIew
- Navigation Controller UINavigationController
  - Navigation Bar      UINavigationBar

Note that there isn't anything in the view. See viewDidLoad below for where the UINavigationController gets attached to the UIView.

In the header file for the Tab's ViewController (which I've here called DescriptiveNameNavViewController -- there isn't a particular standard for this, but I use [Something]NavViewController to remind me that this ViewController contains a navigation controller with the navigation stack. This is the controller name that I set in the MainWindow.xib that the wizard generates) Set up a UINavigationController * IBOutlet that has the navigation controller in the XIB attached to it:

@interface DescriptiveNameNavViewController : UIViewController {
    UINavigationController *navigationController;
}
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

In the controller for the DescriptiveNameNavViewController , do something like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    [[self view] addSubview:[navigationController view]];
    DescriptiveNameController *aController = [[[DescriptiveNameController alloc ] initWithNibName:@"DescriptiveNameController" bundle:nil ] autorelease];
    aController.title = @"Descriptive Title";

//
//  app stuff goes here.
//

    [self.navigationController pushViewController:aController animated:YES];
    [self.navigationController setDelegate:self];
}

Setting the delegate in the DescriptiveNameNavViewController is super-important, because otherwise you won't get the methods called that you expect in DescriptiveNameViewController instances and anything else you push into the navigation controller's stack.

In DescriptiveNameNavViewController, implement the UINavigationControllerDelegate methods like this:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if ([viewController respondsToSelector:@selector(viewDidAppear:)]) {
        [viewController viewDidAppear:animated];
    }
}

And that will cause messages to get propagated to controllers inside the UINavigationController like you expect. It seems like many problems that people encounter are because the viewDidAppear: or other methods aren't getting called on the ViewControllers pushed into the NavigationController.

Anyway, let me know if more detail would help.

Share:
10,936
barfoon
Author by

barfoon

PHP &amp; iOS developer based out of Ottawa.

Updated on June 11, 2022

Comments

  • barfoon
    barfoon almost 2 years

    Hey everyone, I am new to iPhone development and I'm not understanding the whole UINavigationController and UITabBarController idea. Is one a substitute for the other - how do apps such as Tweetie combine both?

    I'd like to have my app have a persistent Tab Bar @ the bottom (which seems to be working), but also a Navigation bar at the top which can push/pop views onto the screen without removing the tab bar.

    • How can I accomplish this?
    • What should the hierarchy look like in IB as far as my MainWindow.xib with regards to all of these controllers?
    • What is best practice here?

    Thanks very much,