4

I have a tab bar based app. All tabs have a navigation controller as the root. If the user taps on the tab again if the tab is active, it pops back to the navigation controller.

How can I stop this behavior?

So in fact I have a navigation controller + a hidden viewcontroller that makes some decisions + another view controller. Sorry for the misleading information in the original question. I use the hidden viewcontroller for all the tabs, 3 of them, since I have the login screen on all 3 if the user is not logged in. If the user logs in, then I pop the login screen, and put the 1,2,3 individual viewcontrollers on each tab.

First tap:

 0 : class=Crossing: 0x645c8a0>  
 1 : class=FavoritesViewController: 0x64ac140>  
 shouldSelectViewController : UINavigationController  
 UINavigationController topclass:FavoritesViewController  
 myTabBarController.selectedViewController :UINavigationController  
 did disappear  
 didSelectViewController : UINavigationController  
 UINavigationController topclass:FavoritesViewController  

Second tap:

 0 : class=Crossing: 0x645c8a0>  
 1 : class=FavoritesViewController: 0x64ac140>  
 shouldSelectViewController : UINavigationController  
 UINavigationController topclass:FavoritesViewController  
 myTabBarController.selectedViewController :UINavigationController  
 didSelectViewController : UINavigationController  
 UINavigationController topclass:Crossing  
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Zsolt
  • 3,648
  • 3
  • 32
  • 47
  • 1
    Related: http://stackoverflow.com/questions/1849975/prevent-automatic-poptorootviewcontroller-on-double-tap-of-uitabbarcontroller – Deepak Danduprolu Jul 05 '11 at 16:39
  • Yes, thanks for the link too. But somehow it does not work in this case. I need to somehow identify which viewcontroller is acted on in the shouldSelect method, so I can do something about it. As the debug log shows, somehow I cannot get my hand on it yet. They look the same. – Zsolt Jul 06 '11 at 15:14

5 Answers5

7

@MarkGranoff was on the right track for doing this, but the way to do it is by doing something like this:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    if ([tabBarController.viewControllers indexOfObject:viewController] == tabBarController.selectedIndex)
    {
        return NO;
    }
    else
    {
        return YES;
    }
}

or in a less verbose way:

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

If you only want to block the default behaviour for a certain tab then you can do something like this:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    NSUInteger indexOfNewViewController = [tabBarController.viewControllers indexOfObject:viewController];
    // Only the second tab shouldn't pop home 
    return ((indexOfNewViewController != 1) ||
            (indexOfNewViewController != tabBarController.selectedIndex));
}
hypercrypt
  • 15,389
  • 6
  • 48
  • 59
4

Swift 3

  1. Subclass your UITabBarController and implement UITabBarControllerDelegate on that class.

    class viewMain: UITabBarController, UITabBarControllerDelegate {

  2. In viewDidLoad, set your class's delegate to be itself

    self.delegate = self

  3. Add this function

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { return (viewController != tabBarController.selectedViewController); }

Pradeep
  • 9,667
  • 13
  • 27
  • 34
Brad C
  • 731
  • 7
  • 5
1

In your application delegate (which I assume is the delegate for your UITabBarController), try implementing tabBarController:shouldSelectViewController: and return NO if the view controller to be selected is not at its root view. This, of course, may backfire for tabs that were switched away from when you try to go back to them... Hmm....

Mark Granoff
  • 16,878
  • 2
  • 59
  • 61
  • 1
    yes, exactly. I tried this, but then you cannot switch tabs. – Zsolt Jul 06 '11 at 06:15
  • 1
    You may have to subclass `UITabBarController` so you can implement your own `popToRootViewController:` method that simply does nothing. Worth a shot, I'd say. – Mark Granoff Jul 06 '11 at 10:58
  • [((UINavigationController*)tbSelectedController) visibleViewController] is another useful method. It works if I have root+1 if I check the 1 class and make sure return NO. But if I have other viewcontrollers on the stack, it will still go back to the root. – Zsolt Jul 09 '11 at 07:40
  • @MarkGranoff UITabBarController doesn't have any popToRootViewController:, that method is implemented by UINavigationController. – 6rod9 Sep 18 '15 at 19:23
0

Update Swift 4.1

Stop Double Tap on only one specific tab. Here it's for 3rd Tab.

extension TabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
    //for blocking double tap on 3rd tab only
    let indexOfNewVC = tabBarController.viewControllers?.index(of: viewController)
    return ((indexOfNewVC != 2) ||
        (indexOfNewVC != tabBarController.selectedIndex))      
}}

Stop Double Tap for all tabs.

extension TabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
    //for blocking double tap on all tabs.
    return viewController != tabBarController.selectedViewController
}}

Thanks!!!

Harjot Singh
  • 6,767
  • 2
  • 38
  • 34
  • Don't forget to set the delegate of the tab bar controller to the object that actually implements this – Roman Sep 19 '19 at 03:05
0

You can check for the view controller in

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController

and you can keep track on the view controllers selected.

Legolas
  • 12,145
  • 12
  • 79
  • 132
  • yes, I use that method, but not sure if I can do anything there in this case. I get the viewcontroller or the navigation controller, but not sure what to do so I do not have a pop back. I do not want to see the navigation controller. – Zsolt Jul 06 '11 at 06:15