screenMonkey MonkeyMan
screenMonkey MonkeyMan

Reputation: 423

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.

Upvotes: 0

Views: 716

Answers (2)

Mario
Mario

Reputation: 2505

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!

Upvotes: 1

Mario
Mario

Reputation: 2505

When you're setting up each view controller for each of the tabs, set the tag property of the UITabBarItem to correspond to the index of the view controller in the tab bar's viewControllers array.

UIViewController* myFirstVC = [[UIViewController alloc] init];
UIViewController* mySecondVC = [[UIViewController alloc] init];

// "self" is your ApolloTabBarController.
[self setViewControllers:@[myFirstVC, mySecondVC]];

myFirstVC.tabBarItem = 
    [[UITabBarItem alloc] initWithTitle:@"First" image:nil tag:0];

mySecondVC.tabBarItem = 
    [[UITabBarItem alloc] initWithTitle:@"Second" image:nil tag:1];

Then, you'll be able to grab a reference to view controller.

// In your example, your ApolloTabBarController acts as its own delegate.
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
    UIViewController* activeVC = 
        [[self viewControllers] objectAtIndex:[item tag]];
}

Upvotes: 0

Related Questions