views:

596

answers:

4

Hi there,

just found out something: If you have a Tabbar combined with a NavigationController (that has some views on it's stack) and you double click the TabBarItem, the view pops to the first ViewController, whether you like it or not.

Is there a way to prevent this?

A: 

The only way I've found so far is to make a subclass of UINavigationController and overwrite the popToRootViewControllerAnimated method to return nil.

This seems to be the method which the UITabBar calls when tabbed twice. I don't know if it's the correct way though... Would love some feedback on the issue...

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated {
    return nil;
}
Jakob Dam Jensen
A: 

I just ran into this problem myself and found a way to do it. Make a delegate for your UITabBarController and implement tabBarController:shouldSelectViewController: to prevent selecting the same controller:

- (BOOL) tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)vc {
  return tbc.selectedViewController != vc;
}

You can also add more complicated logic if you only want to prevent it in some cases.

mckeed
+2  A: 

You probably should not prevent this behavior. It's a standard iPhone UI convention, like tapping the status bar to scroll to the top of a scroll view.

If you really want to do it, you should implement the UITabBarController delegate method -tabBarController:shouldSelectViewController:, like mckeed mentioned. If you have more than five tabs, however, the selectedViewController may be a view controller that is in the "More" section, but vc will be [UITabBarController moreNavigationController]. Here's an implementation that handles that case:

- (BOOL)tabBarController:(UITabBarController *)tbc shouldSelectViewController:(UIViewController *)vc {
    UIViewController *selected = [tbc selectedViewController];
    if ([selected isEqual:vc]) {
        return NO;
    }

    if ([vc isEqual:[tbc moreNavigationController]] &&
        [[tbc viewControllers] indexOfObject:selected] > 3) {
        return NO;
    }

    return YES;
}
lemnar
I also recommend not preventing this behavior without VERY good reasons. Users get pissed off when a system wide shortcut is not available.
Brandon Bodnár
A: 

I agree with keeping this as-intended behavior, but at the same time things get interesting with unwinding the VC stack gracefully (such as when editing a nested series of Core Data objects). In my case, it's tantamount to canceling each VC.

Thus, is there some way for me to know we're popping all the way up to the root VC? I'm thinking a cancel/rollback op during viewWillDisappear doesn't cut it, because that same view would surely disappear after a save as well. I need to somehow broadcast "we're canceling - bail out!" when popping all the way to the root VC in a given tab. Checking a dirty/new flag as a safety check within viewWillDisappear also doesn't help, since that test would then be called twice in the case of a legit cancel (that is, if the cancel button is actually tapped).

Joe D'Andrea
Ah-ha. At first I thought Categories are your friend, and perhaps I could rig one on UIViewController and intervene within popToRootViewControllerAnimated: to alert the troops. But that would require subclassing instead, wouldn't it. (I try to avoid subclassing in Cocoa whenever possible, but this may not be one of those times that it's possible.) If there's a less entropy-laden way around this, I'm all ears.
Joe D'Andrea