Pankaj Wadhwa
Pankaj Wadhwa

Reputation: 3063

Youtube video not playing in landscape mode in iOS 8

My app consist a functionality of playing videos both in landscape and portrait mode.videos can be youtube also everything was working fine till iOS 7 but now youtube videos are not working in landscape mode on iOS 8.

my code:

- (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window {


  if ([[window.rootViewController presentedViewController]
     isKindOfClass:[MPMoviePlayerViewController class]] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")])        {

      return UIInterfaceOrientationMaskAllButUpsideDown;
  } else {

      if ([[window.rootViewController presentedViewController]
         isKindOfClass:[UINavigationController class]]) {

          // look for it inside UINavigationController
          UINavigationController *nc = (UINavigationController *)[window.rootViewController presentedViewController];

          // is at the top?
          if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) {
            return UIInterfaceOrientationMaskAllButUpsideDown;

            // or it's presented from the top?
          } else if ([[nc.topViewController presentedViewController]
                    isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;
          }
      }
  } 

  return UIInterfaceOrientationMaskPortrait;
}

Everything was working fine till iOS 7 but stop working on iOS 8. Any help appreciated

Upvotes: 5

Views: 8099

Answers (6)

CodeOverRide
CodeOverRide

Reputation: 4471

Here is Swift 3 version for iOS 10.1. I've modified Anthony Persaud answer here. To check if presentedController.isKind(of: MPMoviePlayerViewController.self), you'll need import MediaPlayer at the top.

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {

    if let presentedController = window?.rootViewController?.presentedViewController,
        let avFullScreen = NSClassFromString("AVFullScreenViewController").self,
        let mpInlineVideoFullscreen = NSClassFromString("MPInlineVideoFullscreenViewController").self {

        if presentedController.isKind(of: MPMoviePlayerViewController.self) ||
            presentedController.isKind(of: avFullScreen) ||
            presentedController.isKind(of: mpInlineVideoFullscreen) {
            return UIInterfaceOrientationMask.allButUpsideDown
        }
    }

    return UIInterfaceOrientationMask.portrait

}

Upvotes: 0

Pankaj Wadhwa
Pankaj Wadhwa

Reputation: 3063

Well its sometimes silly to answer your own question but its good to help others who are facing the same problem.

in iOS 8 instead of checking for MPInlineVideoFullscreenViewController we need to check for AVFullScreenViewController. So below is the complete method for all iOS versions i.e iOS 8 and less.

 - (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window {

  if ([[window.rootViewController presentedViewController]
     isKindOfClass:[MPMoviePlayerViewController class]] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")] || [[window.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]) {

      return UIInterfaceOrientationMaskAllButUpsideDown;
  }else {

      if ([[window.rootViewController presentedViewController]
         isKindOfClass:[UINavigationController class]]) {

          // look for it inside UINavigationController
          UINavigationController *nc = (UINavigationController *)[window.rootViewController presentedViewController];

          // is at the top?
          if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;

              // or it's presented from the top?
          } else if ([[nc.topViewController presentedViewController]
                    isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;
          }
      }
  }

  return UIInterfaceOrientationMaskPortrait;
}

Update : Works in iOS 9 as well

Upvotes: 14

AhmedZah
AhmedZah

Reputation: 1203

This is a solution in Swift tested on iOS7 and iOS8. You have to add this method to your AppDelegate class.

AppDelegate.swift

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

    var topController = UIApplication.sharedApplication().keyWindow?.rootViewController

    if (topController != nil) {
        while ((topController!.presentedViewController) != nil) {
            topController = topController!.presentedViewController;
        }

        if (topController != nil && (topController!.className == "AVFullScreenViewController" || topController!.className == "MPFullScreenTransitionViewController"))  {
            return Int(UIInterfaceOrientationMask.All.rawValue);
        }

    }

    return Int(UIInterfaceOrientationMask.Portrait.rawValue);
 }

Upvotes: 1

Anthony Persaud
Anthony Persaud

Reputation: 1186

Update: One thing to add if you notice your status bar breaking after you come back to your controller from a landscape video is to set the status bar as not hidden to false in viewWillLayoutSubviews.

   override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .None)
}

For those in Swift, a few additional notes. This method (application:supportedInterfaceOrientationsForWindow) should be in your AppDelegate class or whatever you've set to @UIApplicationMain. In order to have access to the MPMoviePlayerViewController class, you must remember to import MoviePlayer.

Second, the UIInterfaceOrientationMask value is not compatible with the Swift version of the delegate by itself, so you need to access rawValue and transform the resulting Uint into an Int. Here is the Swift solution for those in need.

    func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int {
    var orientation =  UIInterfaceOrientationMask.Portrait

    if let presentedController = window.rootViewController?.presentedViewController {

        //check for the controllers
        if presentedController is MPMoviePlayerViewController ||
           presentedController.isKindOfClass( NSClassFromString("AVFullScreenViewController").self ) ||
           presentedController.isKindOfClass( NSClassFromString("MPInlineVideoFullscreenViewController").self ) {
           orientation = .AllButUpsideDown
        }
        //otherwise, we may be inside a Nav.
        //safely get the nav controller otherwise ignore this block
        else if let navController = presentedController as? UINavigationController {

            if navController.topViewController is MPMoviePlayerViewController ||
               navController.topViewController.isKindOfClass( NSClassFromString("AVFullScreenViewController").self )  ||
               navController.topViewController.isKindOfClass( NSClassFromString("MPInlineVideoFullscreenViewController").self ) {
               orientation = .AllButUpsideDown
            }
        }


    }

   return  Int(orientation.rawValue)
}

Upvotes: 3

hiroshi
hiroshi

Reputation: 7251

I could not detect the AVFullScreenViewController in my app on iOS 8 Golden Master, but finding AVPlayerView does the trick.

UIViewController+VideoAutorotate.h

#import <UIKit/UIKit.h>

@interface UIViewController (VideoAutorotate)

@end

UIViewController+VideoAutorotate.m

#import "UIViewController+VideoAutorotate.h"

BOOL testAnyViewRecursively(UIView *view, BOOL (^test)(UIView *view)) {
    if (test(view)) {
        return YES;
    } else {
        for (UIView *subview in view.subviews) {
            if (testAnyViewRecursively(subview, test)) {
                return YES;
            }
        }
    }
    return NO;
}

@implementation UIViewController (VideoAutorotate)

-(BOOL)shouldAutorotate
{
    if (UI_PAD) {
        return YES;
    } else {
        // iOS 6: MPInlineVideoFullscreenViewController in iOS 6 doesn't seem to override this method to return YES.
        if ([NSStringFromClass([self class]) isEqual:@"MPInlineVideoFullscreenViewController"]) {
            return YES;
        }
        // iOS 8:
        return testAnyViewRecursively(self.view, ^BOOL(UIView *view) {
            return [NSStringFromClass([view class]) isEqual:@"AVPlayerView"];
        });
    }
}

Upvotes: 0

overeasy
overeasy

Reputation: 404

I have similar code in my app, which also broke in iOS8.

I just wanted to post my version of this fix in case it helps anyone.

The main difference is, i'm only checking against the top most presented controller.

I think this makes more sense than the nested conditionals trying to figure out what kind of vc is presenting another vc.

Anyway, I've got this in my app delegate, and it's working great in 8.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    id presentedViewController = [self topMostController];

    if ( [self vcIsVideoPlayer:presentedViewController] ) {
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}

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

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

    return topController;
}

- (BOOL) vcIsVideoPlayer:(UIViewController *)vc {
    NSString *className = vc ? NSStringFromClass([vc class]) : nil;
    return (
            [className isEqualToString:@"MPInlineVideoFullscreenViewController"] ||
            [className isEqualToString:@"MPMoviePlayerViewController"] ||
            [className isEqualToString:@"AVFullScreenViewController"]
            );
}

Upvotes: 5

Related Questions