iPhone Tab bars moreNavigationController not handling navigation controllers correctly?
The moreViewController that appears in a tab bar with more than 5 items seems to treat view controllers correctly but not navigation controllers. Can anyone explain why this is the case?
Here's how to reproduce the problem in prose, then in code:
I create a simple app with 6 UIViewControllers in 6 tabs. Since I have more than 5 tabs, tab "5" and "6" reside in the moreNavigationList. The 6th tab contains a button that, when pressed, removes the first tab. This reduces the number of tabs to 5, so the moreNavigationController is not required anymore and disappears. Tab "6" now moves to the last spot of the tab bar. Everything as expected.
Now, if put the view controller from tab "6" (i.e. the one with the button) into a navigation controller, things break. If I press the button, tab "1" is removed from the tab bar, the moreNavigationController disappears and tab "6" is now displayed in th开发者_StackOverflowe last spot of the tab bar. However it's content is gone. No button, no nothing.
From analyzing the view hierarchy, what seems to be happening is that the moreNavigationController removes the "6" view controller from its original navigation controller in [tabBarController viewControllers] and adds it to its own stack. But it doesn't seem to put it back when the moreNavigationController disappears.
Here's the code I used to reproduce this in a simple window based test app:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create a tab bar with 5 regular view controllers and a navigation controller
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
UIViewController* vc1 = [[[UIViewController alloc] init] autorelease]; vc1.title = @"1";
UIViewController* vc2 = [[[UIViewController alloc] init] autorelease]; vc2.title = @"2";
UIViewController* vc3 = [[[UIViewController alloc] init] autorelease]; vc3.title = @"3";
UIViewController* vc4 = [[[UIViewController alloc] init] autorelease]; vc4.title = @"4";
UIViewController* vc5 = [[[UIViewController alloc] init] autorelease]; vc5.title = @"5";
UIViewController* vc6 = [[[UIViewController alloc] init] autorelease]; vc6.title = @"6";
// Add a button that removes tab "1" when pressed to vc6
UIButton *moveButton = [self moveButton];
[vc6.view addSubview:moveButton];
vc6.view.backgroundColor = [UIColor greenColor];
moveButton.center = vc6.view.center;
UINavigationController* navController = [[[UINavigationController alloc] initWithRootViewController:vc6] autorelease];
// Everything is fine if vc6 is added directly instead of inside a navigation controller
NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, vc3, vc4, vc5, navController, nil];
tabBarController.viewControllers = controllers;
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (UIButton *)moveButton
{
UIButton *moveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
moveButton.frame = CGRectMake(0, 0, 150, 50);
[moveButton setTitle:@"Remove 1" forState:UIControlStateNormal];
[moveButton addTarget:self action:@selector(remove) forControlEvents:UIControlEventTouchUpInside];
return moveButton;
}
- (void)remove
{
// remove 1st tab bar item (this also removes moreNavigationController)
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:tabBarController.viewControllers];
[viewControllers removeObjectAtIndex:0];
[tabBarController setViewControllers:viewControllers];
}
SDK used is 4.3
I ran into the same problem, and spent hours looking into solutions. As it turns out, there isn't really one.
The issue is nested Navigation Controllers. Your Navigation Controller is being placed in moreNavigationController, and the error occurs when it's taken out. As delirus hints, you can use [moreNavigationController popToRootViewControllerAnimated:]
to get the subviews of the Navigation Controller and place them in a new Navigation Controller and display that. I tried this, and found why this issue has never been fixed: Your Navigation Bars will "overlap".
If you go a few views deep in a Navigation Controller, and then it is placed in moreNavigationController, moreNavigationController's Back button will replace your Navigation Controller's Back button. There are a few other situations you'll run into where the Navigation Bars will conflict.
You could create a second toolbar, with your own back buttons, or override how the More button works, but I've found that to remain user intuitive there are only two workarounds - don't embed Navigation Controllers in Tab Bar Controllers, or limit the number of tabs.
I realize this question is a old, but I hope this answer saves someone some trouble. If anyone has any questions (or suggestions for other workarounds!) let me know.
精彩评论