iosobjective-cuitabbarrootviewcontroller

How do I check present viewController or root viewController?


I have set up my class with UITabBarDelegate and implemented its method didSelectItem to detect when a certain tabBar item is pressed. Works great. In each tabBar item I have one containerView that can show a "you have to login"-page if the user is not logged in, and another containerView that present viewControllers that are embedded in a navigationController.

I would like to keep track of the viewController that is presented in the current tab item, and/or the root viewController of that tab.

I have tried a number of different approaches, but most of them return nil or I can't get it to work. I think the whole container situation makes it harder to handle.

It looks something like this:

@interface MyTabBarController () <UITabBarDelegate> 

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {

    NSUInteger indexOfTab = [[tabBar items] indexOfObject:item];

    switch (indexOfTab) {
        case 0: {
            NSLog(@"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
            break;
        }
        case 1: {
           NSLog(@"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
           break;
        }
        case 2: {
           NSLog(@"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);

//These return nil
            NSLog(@"🐳AAAAAA %@", ((UINavigationController*)_appD.window.rootViewController).visibleViewController);
            NSLog(@"🐳AAAAAA %@", ((UITabBarController*)_appD.window.rootViewController).selectedViewController);
            NSLog(@"🐳AAAAAA %@", self.navigationController.topViewController);
            NSLog(@"🐳AAAAAA %@", self.navigationController.visibleViewController);

//This returns with a value, but can't get it to work with conditionals, that is, when I'm in root, the else is triggered
            NSLog(@"🐳AAAAAA %@", self.tabBar.window.rootViewController);

            if(!self.tabBar.window.rootViewController) {
                NSLog(@"🐳🐳🐳THIS IS NOT ROOT🐳🐳🐳");

            }else {
                NSLog(@"🐳🐳🐳this is ROOT🐳🐳🐳");
            }

// This returns nil
            ((UINavigationController*)_appD.window.rootViewController).visibleViewController;
            ((UITabBarController*)_appD.window.rootViewController).selectedViewController;

            //Doesn't work
            if([self.navigationController.viewControllers[0] isKindOfClass:[ExperiencesListViewController class]]) {
                           NSLog(@"🐳IS KIND OF CLASS LIST");
                       }
                       if([self.navigationController.viewControllers[0].childViewControllers isKindOfClass:[ExperiencesContainerViewController class]]) {
                           NSLog(@"🐳IS KIND OF CLASS CONTAINER");
                     }
           break;
       }
        case 3: {
           NSLog(@"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
           break;
       }
        case 4: {
           NSLog(@"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
           break;
       }
        default:
            break;
    }
}

So, what else can I try? Seems like I have to use `self.tabBar.window.rootViewController` in some way, no?

***EDIT*** 
Oh, and I have tried the `tabBarController` delegate but that doesn't trigger. Also, the `tabBar` is constructed programmatically if that helps.


Solution

  • Sorry to have not read your question correctly. Here's what I suggest you do.

    All of these view controllers that you're interested in keeping track of: you should have them send a custom notification from within their -viewDidAppear: (or -viewWillAppear:) method. Then let your ApolloTabBarController object register for that notification. When it gets the notification, you could then store a reference to the view controller. That reference will always point to the active view controller.

    In your individual view controllers, do something like the following:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
    
        [nc postNotificationName:@"XYZViewControllerDidBecomeActiveNotification"
                          object:self];
    }
    

    Of course, you would want to use some kind of constant for the notification name.

    In your ApolloTabBarController class, register for XYZViewControllerDidBecomeActiveNotification and implement something like:

    - (void)viewControllerDidBecomeActive:(NSNotification *)notification
    {
        self.activeViewController = [notification object];
    }
    

    I hope that helps!