entropid entropid - 10 months ago 103
iOS Question

Allow video on landscape with only-portrait app

I have a UIWebView included in a UIViewController which is a descendant of UINavigationController. It looks like this:

Main view

The app is portrait only. When I play the video I want the user to be able to rotate the device and see the video in landscape mode. I use this code to allow it:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
id presentedViewController = [self topMostController];
NSString *className = presentedViewController ? NSStringFromClass([presentedViewController class]) : nil;

if ([className isEqualToString:@"MPInlineVideoFullscreenViewController"] ||
[className isEqualToString:@"MPMoviePlayerViewController"] ||
[className isEqualToString:@"AVFullScreenViewController"]) {
return UIInterfaceOrientationMaskAllButUpsideDown;

return UIInterfaceOrientationMaskPortrait;

- (UIViewController *)topMostController {
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (topController.presentedViewController) {
topController = topController.presentedViewController;

return topController;

And then in my UINavigationController (so when the video finishes the view is not presented in landscape but only in portrait):

- (BOOL)shouldAutorotate
return NO;

- (NSUInteger)supportedInterfaceOrientations
return UIInterfaceOrientationMaskPortrait;

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return UIInterfaceOrientationPortrait;

Everything works perfectly:

Video portrait Video landscape

But then the video is done playing (or the user taps ‘Done’) and the screens return to the underlying view, this is what happens:

Navigation bar issue

As you can see, the navigation bar slips under the status bar.
Additionally, I get a lot of auto-layout errors in the logs: http://pastebin.com/09xHzmgJ

Any idea about how to solve this?

Answer Source

I temporarily solved (through a hack) with the following code in the viewDidLoad of my controller. I have to specify that the code is specifically made for my case: since I explicitly disallow landscape orientation of my UINavigationController (see code above), the usual notification “UIDeviceOrientationDidChange” is not called when the playback finished and the window goes back to portrait. However, I hope there is a better option and this is a bug of the SDK, since it does not appear on iOS 7 and given the amount of auto-layout errors I get related to the video player (on which I have no control).

- (void)viewDidLoad
    [super viewDidLoad];

    // […]

     Hack to fix navigation bar position/height on iOS 8 after closing fullscreen video

     Observe for “UIWindowDidRotateNotification” since “UIDeviceOrientationDidChangeNotification” is not called in the present conditions
     Check if the notification key (“UIWindowOldOrientationUserInfoKey”) in userInfo is either 3 or 4, which means the old orientation was landscape
     If so, correct the frame of the navigation bar to the proper size.

    [[NSNotificationCenter defaultCenter] addObserverForName:@"UIWindowDidRotateNotification" object:nil queue:nil usingBlock:^(NSNotification *note) {
        if ([note.userInfo[@"UIWindowOldOrientationUserInfoKey"] intValue] >= 3) {
            self.navigationController.navigationBar.frame = (CGRect){0, 0, self.view.frame.size.width, 64};

And then…

- (void)dealloc
    [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:@"UIWindowDidRotateNotification"];