Programmatically setting UITabBarController's viewControllers and selectedIndex results in no selected UITabBarItem

StackOverflow https://stackoverflow.com/questions/22904854

Question

I have a weird bug in both iOS 6 and 7 with the following UITabBarController subclass code:

self.viewControllers = @[self.myKitchenNavigationController,
                         self.photosIndexNavigationController,
                         self.postNavigationController,
                         self.feedNavigationController,
                         self.talkNavigationController];

self.selectedIndex = 0;
// self.selectedViewController = self.myKitchenNavigationController; // This doesn't help either

If I programmatically set viewControllers (previously nil) and immediately set a selectedIndex then the tab bar appears with no selection.

I had the impression that setting a selected index just after modifying the controllers was somehow "too" soon, so I wrapped that call inside a dispatch_async call:

// Fix selection by dispatching async
dispatch_async(dispatch_get_main_queue(), ^
{
    self.selectedIndex = 0;
});

Now it works, but I wonder if this is a SDK long-standing bug.


Actually the bug is still there, the full method:

- (void)setMode:(RootViewControllerMode)mode
{
    if (_mode == mode)
        return;

    NBULogInfo(@"%@ %d", THIS_METHOD, mode);

    _mode = mode;

    switch (mode)
    {
        case RootViewControllerLoggedMode:
        {
            self.viewControllers = @[self.myKitchenNavigationController,
                                     self.photosIndexNavigationController,
                                     self.postNavigationController,
                                     self.feedNavigationController,
                                     self.talkNavigationController];

            // Fix selection by dispatching async
            dispatch_async(dispatch_get_main_queue(), ^
            {
                self.selectedIndex = 0;
            });

            // Adjust post button
            self.postButtonHidden = NO;
            [self.view addSubview:self.postButton];
            break;
        }
        case RootViewControllerNotLoggedMode:
        {
            self.viewControllers = nil;

            // Remove post button to tabBar
            [self.postButton removeFromSuperview];
            break;
        }
        default:
        case RootViewControllerEmptyMode:
        {
            self.viewControllers = nil;
            break;
        }
    }
}

This is the only code that touches the tab bar controller's viewControllers and the current selected tab.

Already verified this was called on the main thread, then also tried wrapping everything inside dispatch_async in the main queue, and finally tried dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), and still the problem persists.

Was it helpful?

Solution

Modifying the tab bar's viewControllers seems to be quite bug-prompt, besides the problem here also tab item badges appear sometimes behind the selectionIndicatorImage.

We end up setting the controllers in a storyboard and avoid modifying the controller's or their order.

OTHER TIPS

YourAppDelegate* appDelegate = (id)[UIApplication sharedApplication].delegate;
appDelegate.yourTabBar.selectedIndex = 1;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top