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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3239231/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:25:10  来源:igfitidea点击:

Properly displaying and dismissing fullscreen MPMoviePlayerController in iOS 3.2 (iPad)

iphonecocoa-touchipadmpmovieplayercontrollerios

提问by jbrennan

I'm having lots of trouble displaying a fullscreen movie in my iPad app and then allowing the user to dismiss it with either the Done button or the "un-fullscreen" button on the player controls.

我在 iPad 应用程序中显示全屏电影时遇到了很多麻烦,然后允许用户使用“完成”按钮或播放器控件上的“非全屏”按钮关闭它。

Initially I was using MPMoviePlayerViewControllerfor the movie presentation, but I wasn't receiving the enter/exit fullscreen notifications from its MPMoviePlayerControllerobject, so I switched to doing it myself.

最初我MPMoviePlayerViewController用于电影演示,但我没有收到来自其MPMoviePlayerController对象的进入/退出全屏通知,所以我转而自己做。

I can make the movie appear fullscreen (although the transition is janky), but when either the "Done" or "un-fullscreen" buttons are pressed, no action is taken by the player. I've posted my code below:

我可以让电影全屏显示(尽管过渡很卡),但是当按下“完成”或“非全屏”按钮时,播放器不会执行任何操作。我在下面发布了我的代码:

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

}

And here is the code for my didFinish callback

这是我的 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];
}

So obviously I am doing something wrong but I've been up and down the documentation and I can't figure out how to make the movie just go away. I figured it would be more intuitive than this. What am I doing wrong?

所以很明显我做错了什么,但我一直在翻阅文档,我不知道如何让电影消失。我想这会比这更直观。我究竟做错了什么?

回答by Art Gillespie

Here are how the events -> notifications work:

以下是事件 -> 通知的工作方式:

  • User presses 'Done' button

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
  • User presses 'Leave fullscreen' button on transport

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
    • Note that playback does not stop
  • Movie reaches end

    • MPMoviePlayerPlaybackDidFinishNotificationwith the MPMoviePlayerPlaybackDidFinishReasonUserInfoKeyset to MPMovieFinishReasonPlaybackEnded
    • If you call setFullscreen:NO animated:YESon your MoviePlayerController instance from this notification, you'll then get the WillExitand DidExitnotifications.
    • Note that you don't get the PlaybackDidFinishnotification when the user presses the Done or Leave Fullscreen buttons.
  • 用户按下“完成”按钮

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
  • 用户在传输时按下“离开全屏”按钮

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

    • MPMoviePlayerPlaybackDidFinishNotificationMPMoviePlayerPlaybackDidFinishReasonUserInfoKey设置为MPMovieFinishReasonPlaybackEnded
    • 如果您setFullscreen:NO animated:YES从此通知调用您的 MoviePlayerController 实例,您将收到WillExitDidExit通知。
    • 请注意,PlaybackDidFinish当用户按下“完成”或“离开全屏”按钮时,您不会收到通知。

So, typically, if you want to get rid of the MoviePlayer's view, you need to put [self.moviePlayerController.view removeFromSuperview]in the DidExitFullscreennotification handler. WillExitFullscreenis too soon.

因此,通常情况下,如果你想摆脱MoviePlayer的看法,你需要把[self.moviePlayerController.view removeFromSuperview]DidExitFullscreen通知处理程序。WillExitFullscreen太快了。

Here's my code:

这是我的代码:

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

回答by Agat

Yes. That's great. There are really notifications mentioned above...

是的。那太棒了。确实有上面提到的通知......

However, there are no MPMoviePlayerPlaybackWillFinishNotification somewhy!!! That's really a problem.

但是,为什么没有 MPMoviePlayerPlaybackWillFinishNotification !!!这真的是一个问题。

When you call the movie player as modal (no matter which of the following methods used presentViewController/presentModalViewController/presentVideoController), if you defined .fullScreen = YES, it's not expected to call MPMoviePlayerWillExitFullscreenNotificationnotification at all(obviously, because it's not cosidering we enter/exit from full screen, but only present/dismiss the controller).

当你调用电影播放器模式(不管下面的方法,其使用presentViewController / presentModalViewController / presentVideoController),如果定义.fullScreen = YES,它预计不会调用MPMoviePlayerWillExitFullscreenNotification通知所有(很明显,因为它不是cosidering我们进入/退出全屏,但只显示/关闭控制器)。

But there are really no any notifications that the video is about to finish and close. That's needed (besides any other situations possible) to catch the moment when the transition of dismissing is started. (The transition, of course, starts before the MPMoviePlayerPlaybackDidFinishNotificationcalled). And, at the same time, application:supportedInterfaceOrientationsForWindow: for previously shown controller is called before the notification, and there is no way to say the AppDelegate that our current controller must be shown already in another orientation.

但是实际上没有任何关于视频即将结束和关闭的通知。这是需要的(除了任何其他可能的情况)来捕捉解雇转换开始的时刻。(当然,转换在调用MPMoviePlayerPlaybackDidFinishNotification之前开始)。并且,同时,application:supportedInterfaceOrientationsForWindow: for 之前显示的控制器在通知之前被调用,并且没有办法说 AppDelegate 必须已经在另一个方向显示我们当前的控制器。

So, since my video is fullscreen and also without any controls shown (this is kind of an intro, so I just until it finishes) my solution was just to have a timer which checks every short tick (0.1 seconds) what is the video current position... and it it's close to the end, then this is the moment for my own notification.

因此,由于我的视频是全屏的并且没有显示任何控件(这是一种介绍,所以我只是在它完成之前)我的解决方案只是有一个计时器来检查每个短滴答声(0.1 秒)当前的视频是什么位置......它接近尾声,那么现在是我自己通知的时刻。