views:

572

answers:

1

I'm trying to write an application that uses a navigation bar and tab bar in what (I'm gathering) is an unusual manner.

Basically, I've got several "pages" ("home", "settings", etc) that each have their own tab. I'd also like to have it so that the "home" page is the root view of the navigation bar, and the other pages are the second-level views of the navigation bar. That is, I should be able to navigate to any page by clicking the appropriate tab bar item, and should be able to navigate to the home page from any other page by clicking the navigation bar's back button.

Currently, I have a UINavigationBar (through a UINavigationController) and a UITabBar (through a UITabController) as children of a UIView. The various pages' view controllers are set as the tab controller's viewControllers property, and the home page's controller is also set as the navigation controller's root view. Each page view's tag is set to its index in the tab control. I have the following logic in the tab controller's didSelectViewController delegate method:

- (void) tabBarController:(UITabBarController*) tabBarController
    didSelectViewController:(UIViewController*) viewController
{
    if ([navController.viewControllers count] > 1)
        [navController popViewControllerAnimated:NO];

    [navController pushViewController:viewController animated:YES];
}

Also, in the navigation controller's didShowViewController delegate method, I have the following code:

- (void) navigationController:(UINavigationController *) navigationController
    didShowViewController:(UIViewController *)viewController
    animated:(BOOL)animated
{
    tabController.selectedIndex = viewController.view.tag;
}

The problem that's occurring is that when I run this, the navigation bar, tab bar and home page all display ok, but the tab bar will not respond to input - I cannot select a different tab.

I gather it's more usual to have the tab bar as the child of the navigation control, or vice versa. This doesn't seem to fit my approach, because I don't want to have to individually create the subordinate control each time a change occurs in the parent control - eg: recreate tab bar each time the navigation bar changes.

Does anyone have suggestions as to what's wrong and how to fix it? I'm probably missing something obvious, but whatever it is I can't seem to find it. Thanks!

EDIT: I'm guessing it has something to do with both controller's trying to have ownership of the page controller, but I can't for the life of me figure out a way around it.

+1  A: 

Yikes. You're way out on a limb here. I've learned the hard way that UINavigationController and UITabBarController aren't very accommodating when you try to use them in nonstandard ways. UINavigationBar and UITabBar weren't designed to coexist as siblings in the view hierarchy. They really want to be distant cousins. Maybe the approach you're pursuing can be made to work somehow, but I personally wouldn't even attempt it.

With that said, I'll suggest one thing you can check, and then I'll tell you how I'd approach the problem.

Have you implemented, and are you returning YES from tabBarController:shouldSelectViewController: in your UITabBarControllerDelegate? If not, that would prevent your tabs from switching.

Assuming that won't solve all your problems, here's what I would do to get the behavior you're seeking:

  1. Create a UITabBarController and set its view as the root view of your window.

  2. Have a separate UINavigationController under each tab, each with its own navigation bar. (This is the standard way to use UINavigationController and UITabBarController together.)

  3. Set a UITableViewController that displays an identical copy of your main menu table as the root view controller for each navigation controller.

  4. When a row is selected on your "Home" view controller, switch to the associated content tab.

  5. Set a delegate on your UITabBarController. In its tabBarController:didSelectViewController method, call pushViewController:animated:. This is similar to what you're currently doing, except you'll be calling it on (UINavigationController *)tabBarController.selectedViewController.

  6. In the viewDidAppear:animated: of the root view controllers of your content tabs, switch to the "Home" tab. This way, when the user hits the back button to go back to "Home", it will switch to the right tab. (You may also need conditional code to prevent this from happening when the user first selects a content tab. I'm not sure.)

I'll be curious to know if Apple accepts this nonstandard behavior. Come back and let us know. Also, let us know if you get your approach working somehow.

cduhn
I think I might do things your way. I came up with a potential solution using a "naked" UINavigationBar and UITabBar, but it's being much too much trouble to implement. I'll report back when I get something working.
Mac