在没有 NSNotificationCenter 的情况下,在 iOS 8 中正确强制或允许 Youtube 嵌入视频的横向模式

Posted

技术标签:

【中文标题】在没有 NSNotificationCenter 的情况下,在 iOS 8 中正确强制或允许 Youtube 嵌入视频的横向模式【英文标题】:Properly force or allow Landscape mode for Youtube embedded video in iOS 8 without NSNotificationCenter 【发布时间】:2014-12-28 23:17:58 【问题描述】:

当 youtube 播放器在 ios 8 中以全屏模式进入或退出全屏模式时,我遇到了捕捉问题,因为这些通知已被删除 UIMoviePlayerControllerDidEnterFullscreenNotificationUIMoviePlayerControllerWillExitFullscreenNotification 对于此版本的操作系统版本。

因为我的应用项目设置为仅在纵向模式下播放时视频不会旋转到横向模式,这在您的设备上观看视频时确实不太用户友好。

当视频以全屏模式进入时,用户通常希望以纵向模式或横向模式观看视频。

这是我为 iOS 7 做的方式,它运行完美,但在 iOS 8 中却不行。

首先,我将在我的AppDelegate.h 中使用布尔属性在我的AppDelegate.m 中设置这个函数,我称之为videoIsInFullscreen 和函数,

// this in the AppDelegate.h
@property (nonatomic) BOOL videoIsInFullscreen;


// This in my AppDelegate.m to allow landscape mode when the boolean property is set to yes/true.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    if(self.videoIsInFullscreen == YES)
    
        return UIInterfaceOrientationMaskAllButUpsideDown;
    
    else
    
        return UIInterfaceOrientationMaskPortrait;
    

然后在我的ViewController.m 首先,我会在#import "AppDelegate.h" 这样做之后,我会在我的viewDidLoad 方法中添加一些通知..

-(void)viewDidLoad 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerStarted) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerEnded) name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];


当然不要忘记删除它们..

-(void)dealloc 

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];


然后,当这些通知被触发时,我的函数会被调用......这是我允许横向模式然后将其设置回纵向的地方。我的应用就是这种情况,因为它仅设置为纵向支持,但我不希望在 youtube 视频中使用此功能。

// first we set our property in the our AppDelegate to YES to allow landscape mode
- (void)playerStarted

    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = YES;

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];


// Then I will set the property to NO and force the orientation to rotate to portrait.
- (void)playerEnded
       
    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

但是,iOS 8 的情况并非如此。这些通知不再适用于 iOS 8,因此,我使用这些通知发现了类似的东西,但我不太高兴,因为它们对于视频播放器来说不是 100% 准确的。 UIWindowDidBecomeVisibleNotificationUIWindowDidBecomeHiddenNotification 那么,我怎样才能正确地做到这一点,或者至少对于我的 youtube 嵌入式视频可以正常工作并在 iOS 8 中允许横向模式...?

【问题讨论】:

【参考方案1】:

我正在开发 swift,我的播放器在纵向和横向方向上运行电影。首先我检查了三种模式:纵向、横向、横向。 其次我在所有viewController中都写了这个函数:

 isFullScreen = false
override func shouldAutorotate() -> Bool 
    if isFullScreen == true 
        return true
    else
        return false
    

第三,我在这个函数中改变isFullScreen的值:

func playerView(playerView: YTPlayerView!, didChangeToState state: YTPlayerState) 
    switch (state) 
        case  YTPlayerState.Playing:
                println("started to play")
        isFullScreen == true
        shouldAutorotate()
        case YTPlayerState.Paused:
                println("paused")
        default:
            println("non of sttate")
        break
    

视频可在纵向和横向模式下运行!有趣的是,当我暂停视频或从全屏移动时,我不会再次将 isFullScreen 设置为 false。然而它不旋转!有人可以解释一下吗?

【讨论】:

【参考方案2】:

所以,经过一些研究并更深入地研究这个问题.. 我使用UIWebView 代表找到了一个解决方案,另外我必须解决我的函数- (void)playerEnded 的另一个问题,它不是t 在新的 iPhone 6 设备上正常工作..

我就是这样做的。首先,在我的webViewDidFinishLoad 方法中,我向我的 webview 添加了一个 javascript 评估,以检查此视频播放器何时进入全屏模式。

- (void)webViewDidFinishLoad:(UIWebView*)webView

    // adding listener to webView
    [_webView stringByEvaluatingJavaScriptFromString:@" for (var i = 0, videos = document.getElementsByTagName('video'); i < videos.length; i++) "
                                                     @"      videos[i].addEventListener('webkitbeginfullscreen', function() "
                                                     @"           window.location = 'videohandler://begin-fullscreen';"
                                                     @"      , false);"
                                                     @""
                                                     @"      videos[i].addEventListener('webkitendfullscreen', function() "
                                                     @"           window.location = 'videohandler://end-fullscreen';"
                                                     @"      , false);"
                                                     @" "
                                                     ];

然后,在我的 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 方法中,我检查我的请求 url 何时与 youtube 播放器的状态匹配,如下所示.. 这将触发我们的功能以允许横向模式或强制返回纵向模式..或者您可能想要做的任何其他类型的工作..

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 

    // allows youtube player in landscape mode
    if ([request.URL.absoluteString isEqualToString:@"ytplayer://onStateChange?data=3"])
    
        [self playerStarted];

        return NO;
    
    if ([request.URL.absoluteString isEqualToString:@"ytplayer://onStateChange?data=2"])
    
        [self playerEnded];

        return NO;
    

最后,我需要调整我的 playerEnded 函数以强制 iPhone 6 设备返回纵向模式..

- (void)playerEnded

    [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:@"orientation"];

    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;

    [self supportedInterfaceOrientations];

    [self shouldAutorotate:UIInterfaceOrientationPortrait];

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

差点,错过了我还加了这两个功能..

- (NSInteger)supportedInterfaceOrientations

    return UIInterfaceOrientationMaskPortrait;


- (BOOL)shouldAutorotate:(UIInterfaceOrientation)interfaceOrientation

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

所以,我终于能够捕捉到实际玩家的状态,并在适当的时候触发我的函数来做一些工作或任何我想做的事情,在我的情况下改变方向..

我希望这对其他人有所帮助..

【讨论】:

试过了 - 没有达到 -playerStarted 并且播放器结束了。 equest.URL.absoluteString 主要是 about:blank 和 youtube.com/embed..... - 那是在播放视频之前。当视频播放时,shouldStartLoadWithRequest 正在触发。有什么想法吗? shouldStartLoadWithRequest 会在视频播放时触发,您可以捕捉到如上所示的状态。我不确定我是否正确理解了您的问题。没有通知涉及..如果您在 webview 的 iframe 中使用 youtube 嵌入视频,则此方法有效.. 好吧,它没有:(我把 NSLog(@"URL: %@",request.URL.absoluteString); 放在函数的开头,点击播放时我没有打印出来 嗯..这很有趣,您可以用您的代码提出问题吗?更详细地了解问题所在..我猜它应该是 youtube 播放器的配置你的 iframe...我有一个 javascript 可以创建播放器并加载视频等等... 嗯... js 加载 youtube?我只是用 @""。你能把你的 js init 放到一个 pastebin 里吗?

以上是关于在没有 NSNotificationCenter 的情况下,在 iOS 8 中正确强制或允许 Youtube 嵌入视频的横向模式的主要内容,如果未能解决你的问题,请参考以下文章

NSnotificationCenter 正确使用姿势, removeObject 探索

在没有 NSNotificationCenter 的情况下,在 iOS 8 中正确强制或允许 Youtube 嵌入视频的横向模式

关闭时未收到 NSNotificationCenter 通知

NSNotificationCenter PasteboardChangedNotification未触发

细说KVO & KVC & NSNotificationCenter那些事

iOS NSNotificationCenter详解