在iOS 3.2(iPad)中正确显示和关闭全屏MPMoviePlayerController

22

我在iPad应用程序中尝试显示全屏电影并允许用户使用播放控制器上的“完成”按钮或“退出全屏”按钮来关闭它时遇到了很多麻烦。

起初,我使用 MPMoviePlayerViewController 作为电影播放器,但是我没有收到其 MPMoviePlayerController 对象的进入/退出全屏的通知,所以我改为自己实现。

我能够使电影全屏显示(虽然过渡效果不太好),但是当按下“完成”或“退出全屏”按钮时,播放器没有任何反应。我在下面发表了我的代码:

- (void)startPlayingMovieWithURLString:(NSString *)movieURLString {
    // I get all of these callbacks **EXCEPT** the "willExitFullScreen:" callback.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullScreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullScreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishPlayback:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

    [self.moviePlayerController setContentURL:someExistingURL];

        // "self" is a UIViewController subclass, and is presented as a "fullscreen" modal view controller from its parent
        // I'm setting the movie player's view's frame to take up the full rectangle of my view controller, but really I want the movie to be completely removed when the user presses "done" (that is, removed from the view hierarchy). Not sure when/where to do this.
    self.moviePlayerController.view.frame = self.view.frame;
    [self.view addSubview:self.moviePlayerController.view];
    [self.moviePlayerController setFullscreen:YES animated:YES];

}

这里是我的didFinish回调函数的代码

- (void)didFinishPlayback:(NSNotification *)notification {
        // This ends up recursively telling the player that playback ended, thus calling this method, thus…well you get the picture.
        // What I'm trying to do here is just make the player go away and show my old UI again.
    [self.moviePlayerController setFullscreen:NO animated:YES];
}

很明显我做错了什么,但我已经查阅了文档,却不知道该如何让电影消失。我认为它应该比这更直观。我做错了什么?

2个回答

66

以下是事件通知的工作原理:

  • 用户点击“完成”按钮

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
  • 用户在传输控件上点击“退出全屏”按钮

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
    • 请注意,播放不会停止
  • 电影播放结束

    • MPMoviePlayerPlaybackDidFinishNotification 并且 MPMoviePlayerPlaybackDidFinishReasonUserInfoKey 被设置为 MPMovieFinishReasonPlaybackEnded
    • 如果你在这个通知中从 MoviePlayerController 实例调用 setFullscreen:NO animated:YES,那么你将会获得 WillExitDidExit 通知。
    • 请注意,当用户点击“完成”或“退出全屏”按钮时,你不会收到 PlaybackDidFinish 通知。

因此,通常情况下,如果你想要摆脱 MoviePlayer 的视图,你需要在 DidExitFullscreen 通知处理程序中添加 [self.moviePlayerController.view removeFromSuperview]。而 WillExitFullscreen 通知则太早了。

下面是我的代码:

- (void)willEnterFullscreen:(NSNotification*)notification {
    NSLog(@"willEnterFullscreen");
}

- (void)enteredFullscreen:(NSNotification*)notification {
    NSLog(@"enteredFullscreen");
}

- (void)willExitFullscreen:(NSNotification*)notification {
    NSLog(@"willExitFullscreen");
}

- (void)exitedFullscreen:(NSNotification*)notification {
    NSLog(@"exitedFullscreen");
    [self.movieController.view removeFromSuperview];
    self.movieController = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)playbackFinished:(NSNotification*)notification {
    NSNumber* reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
    switch ([reason intValue]) {
        case MPMovieFinishReasonPlaybackEnded:
            NSLog(@"playbackFinished. Reason: Playback Ended");         
                break;
        case MPMovieFinishReasonPlaybackError:
            NSLog(@"playbackFinished. Reason: Playback Error");
                break;
        case MPMovieFinishReasonUserExited:
            NSLog(@"playbackFinished. Reason: User Exited");
                break;
        default:
            break;
    }
    [self.movieController setFullscreen:NO animated:YES];
}

- (void)showMovie {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enteredFullscreen:) name:MPMoviePlayerDidEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitedFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];

    NSURL* movieURL =  [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tron" ofType:@"mov"]];
    self.movieController = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
    self.movieController.view.frame = self.view.frame;
    [self.view addSubview:movieController.view];
    [self.movieController setFullscreen:YES animated:YES];
    [self.movieController play];
}

1
这很有帮助,现在当用户按下“完成”时,我能够退出全屏模式了。然而,对于我来说,“-playbackFinished:”回调从未执行过,我无法想出任何原因。你知道为什么会发生这种情况吗? - jbrennan
即使电影播放到结尾也会出现这种情况吗?这很奇怪,我从未遇到过这种情况。 - Art Gillespie
3
如果MPMoviePlayerDidExitFullscreenNotification在触摸“完成”和退出全屏时都被调用,你该如何知道哪个被调用了?也许用户只是退出了全屏模式,这种情况下你不想移除视图吧。 - Max MacLeod
2
请注意,在MPMoviePlayer [Will / Did] [Exit / Enter] FullscreenNotifications中更改控件样式会使后续通知出现故障:http://www.openradar.me/10607169 - diachedelic
最好的答案,非常感谢。 - Mutawe

0

是的。太好了。上面确实提到了通知...

然而,不知何故没有 MPMoviePlayerPlaybackWillFinishNotification!!!这真的是个问题。

当您将电影播放器调用为模态(无论使用 presentViewController/presentModalViewController/presentVideoController 中的哪一个方法),如果您定义了.fullScreen = YES,则不应该在所有情况下调用 MPMoviePlayerWillExitFullscreenNotification 通知(显然,因为它不考虑我们进入/退出全屏,而只是呈现/解除控制器)。

但是,确实没有任何通知表明视频即将完成并关闭。这是必要的(除了可能发生的任何其他情况),以捕获开始解除的时刻。(当然,在调用 MPMoviePlayerPlaybackDidFinishNotification 之前,过渡已经开始)。同时,在通知之前会为先前显示的控制器调用 application:supportedInterfaceOrientationsForWindow:,并且没有办法告诉 AppDelegate 我们当前的控制器必须以另一种方向显示。

因此,由于我的视频是全屏且没有任何控件显示(这是一种介绍方式,所以我只需要等到它完成),我的解决方案就是设置一个计时器,每隔短时间(0.1秒)检查视频当前位置...如果接近结尾,那么这就是我自己通知的时刻。


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