Search code examples
iosiphoneios8uiinterfaceorientation

Launching into portrait-orientation from an iPhone 6 Plus home screen in landscape orientation results in wrong orientation


The actual title for this question is longer than I can possibly fit:

Launching an app whose root view controller only supports portrait-orientation but which otherwise supports landscape orientations on an iPhone 6 Plus while the home screen is in a landscape orientation results in a limbo state where the app's window is in a landscape orientation but the device is in a portrait orientation.

In short, it looks like this:

When it is supposed to look like this:

Steps to Reproduce:

  1. iPhone 6 Plus running iOS 8.0.

  2. An app whose plist supports all-but-portrait-upside-down orientations.

  3. The root view controller of the app is a UITabBarController.

  4. Everything, the tab bar controller and all its descendent child view controllers return UIInterfaceOrientationMaskPortrait from supportedInterfaceOrientations.

  5. Start at iOS home screen.

  6. Rotate to landscape orientation (requires iPhone 6 Plus).

  7. Cold-launch the app.

  8. Result: broken interface orientations.

I can't think of any other way to enforce a portrait orientation except to disable landscape altogether, which I can't do: our web browser modal view controllers need landscape.

I even tried subclassing UITabBarController and overriding supportedInterfaceOrientations to return the portrait-only mask, but this (even with all the other steps above) did not fix the issue.


Here's a link to a sample project showing the bug.



Solution

  • This appears to be a bug in iOS 8 when using a UITabBarController as a root view controller. A workaround is to use a mostly vanilla UIViewController as the root view controller. This vanilla view controller will serve as the parent view controller of your tab bar controller:

    ///------------------------
    /// Portrait-Only Container
    ///------------------------
    
    @interface PortraitOnlyContainerViewController : UIViewController
    
    @end
    
    @implementation PortraitOnlyContainerViewController
    
    - (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskPortrait;
    }
    
    @end
    
    // Elsewhere, in app did finish launching ...
    
    PortraitOnlyContainerViewController *container = nil;
    
    container = [[PortraitOnlyContainerViewController alloc] 
                  initWithNibName:nil 
                  bundle:nil];
    
    [container addChildViewController:self.tabBarController];
    self.tabBarController.view.frame = container.view.bounds;
    [container.view addSubview:self.tabBarController.view];
    [self.tabBarController didMoveToParentViewController:container];
    
    [self.window setRootViewController:container];