Josh Luongo Josh Luongo - 4 months ago 36
iOS Question

UITabBarController + UINavigationController and more tab black screen issue

I'm currently working on an update to one of my apps and I have come across a very strange issue to do with UITabBarController.

In my storyboard I have about 8 view controllers and in my UITabBarController subclass I add another 4 view controllers that are loaded programmatically. Most of these views need to have to UINavigationController to keep consistency when rotating as some views come out from the "More" tab into the main bar, in order to do this I have embeded them in a UINavigationController.

If you choose view 6 in portrait and the rotate the UINavigationController goes black when the view gets its own button in the tab bar, however when it returns to "more" the view comes back. In my investigation of these it seems that the UINavigationController losses the UIViewController as it root view controller.

Working as expected on a view that does not enter the "More" tab:

Black screen if the view came from the "More" tab:

I made a quick sample project that has this issue:

Any ideas on how to fix this?


I have found a workaround that seems to get around this issue.

By overriding the UITraitCollection in a UITabBarController subclass you can force the horizontalSizeClass to always be UIUserInterfaceSizeClassCompact. This will make the UITabBar only ever have 5 items regardless of the orientation.

Here some sample Objective-C code:

- (UITraitCollection *)traitCollection {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        // Workaround to fix the iPhone 6 Plus roatation issue.
        UITraitCollection *curr = [super traitCollection];
        UITraitCollection *compact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];

        return [UITraitCollection traitCollectionWithTraitsFromCollections:@[curr, compact]];

    return [super traitCollection];

Then if you need access to real traits then override -traitCollection in your UIViewController to return the traits from [UIScreen mainScreen].

Here some example Objective-C code to do that:

- (UITraitCollection *)traitCollection {
    return [UIScreen mainScreen].traitCollection;

This not an ideal solution but until Apple decides to fix this bug, this will do the job.

I hope this helps someone.