iOS 8中无法在横屏模式下播放YouTube视频

5

我的应用程序包含一个在横屏和竖屏模式下播放视频的功能。视频可以是来自YouTube的,之前一切正常,但是从iOS 8开始,在iOS 8上无法在横屏模式下播放YouTube视频。

我的代码:

- (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;
}

在iOS 7上一切都很好,但在iOS 8上停止工作了。任何帮助将不胜感激。

6个回答

14

有时候自己回答自己的问题可能有些傻,但为遇到同样问题的人提供帮助是很好的。

iOS8中,我们需要检查AVFullScreenViewController而不是MPInlineVideoFullscreenViewController。所以下面是适用于所有iOS版本(即iOS8及以下版本)的完整方法。

 - (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;
}

更新: 在iOS 9中也可以工作


4
因为回答自己的问题并不愚蠢,所以我给你点赞了。未回答的堆栈帖子才是愚蠢的。 - overeasy
谢谢您的回答,我在iOS7上使用它时遇到了问题 - 细节太多了,无法在评论中解决,因此我发布了一个新的问题:http://stackoverflow.com/questions/26443485/fullscreen-video-screen-is-not-mpmovieplayerviewcontroller-on-ios7-device - Boaz
谢谢您!当视频视图处于活动状态时,旋转功能按预期工作。但我遇到了一个问题,就是在应用程序处于横向模式时,我点击完成按钮后,应用程序返回纵向模式,但导航栏无法正确调整大小。导航栏的高度比应该的要小。 - William Chen
@WilliamChen,我不知道为什么你的导航栏高度会减小。也许提出一个单独的问题会得到其他人的帮助。 - Pankaj Wadhwa
你好,我们能否在不添加应用程序委托代码的情况下完成这个任务?谢谢! - Ted
请将"applicationsupportedInterfaceOrientationsForWindow"更正为"application supportedInterfaceOrientationsForWindow"。 - Silviu St

5

我在我的应用中有类似的代码,也在iOS8中出现了问题。

我想分享一下我对此修复的版本,以帮助需要的人。

主要区别是,我只检查最顶层的控制器。

我认为这比嵌套条件更容易理解,可以确定哪种类型的视图控制器正在呈现另一个视图控制器。

无论如何,我将其放在我的应用程序委托中,在iOS 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"]
            );
}

1
这个程序完美运行,但当视频停止播放时,底层视图控制器会以横向模式呈现! - entropid
运行得很好。谢谢。 - devxoul

3

更新: 如果在从横向视频返回控制器后发现状态栏出现问题,可以在 viewWillLayoutSubviews 中将状态栏设置为未隐藏(false)。

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

对于使用Swift的人,需要注意以下几点。这个方法(application:supportedInterfaceOrientationsForWindow)应该在你的AppDelegate类中或者其他你设置为@UIApplicationMain的类中。为了能够访问MPMoviePlayerViewController类,你必须记得import MoviePlayer
其次,UIInterfaceOrientationMask值本身不兼容Swift版本的委托,因此你需要访问rawValue并将结果转换为Int类型的Uint。下面是Swift解决方案,供有需要的人参考。
    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)
}

1
这是一个在iOS7和iOS8上测试过的Swift解决方案。您需要将此方法添加到您的AppDelegate类中。

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);
 }

我遇到了这个错误:Objective-C方法'application:supportedInterfaceOrientationsForWindow:'提供的方法'application(:supportedInterfaceOrientationsForWindow:)'与协议'UIApplicationDelegate'中的可选要求方法'application(:supportedInterfaceOrientationsForWindow:)'冲突。你还需要做些什么来实现这段代码吗? - tomDev

0

这里是适用于iOS 10.1的Swift 3版本。我在这里修改了Anthony Persaud的答案。要检查presentedController.isKind(of: MPMoviePlayerViewController.self),您需要在顶部添加import MediaPlayer

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

}

0

我在iOS 8 Golden Master上无法检测到我的应用程序中的AVFullScreenViewController,但是找到AVPlayerView就可以解决问题。

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"];
        });
    }
}

你无法检测到AVFullScreenViewController,因为你正在检查视图而不是视图控制器。 - overeasy
当我尝试在我的代码中为iOS 6查找AVFullScreenViewController时,使用类似于[self class]的行。 - hiroshi
@Rajat 感谢您收集了一些拼写和语法方面的问题,但是我指的 GM 是“Golden Master”,而不是 GSM(全球移动通信系统)。 - hiroshi
@hiroshi 谢谢你的纠正。至于你的评论,GSM现在已经更新为Golden Master。 - iYoung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接