web-dev-qa-db-ja.com

iOS 3.2(iPad)でのフルスクリーンMPMoviePlayerControllerの適切な表示と非表示

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

だから明らかに私は何か間違っているのですが、私はドキュメンテーションを上下に行っており、映画をただ消えさせる方法を理解することができません。これよりも直感的だと思いました。何が悪いのですか?

22
jbrennan

イベント->通知の仕組みは次のとおりです。

  • ユーザーが[完了]ボタンを押す

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
  • ユーザーがトランスポートの[全画面表示を終了]ボタンを押す

    • MPMoviePlayerWillExitFullscreenNotification
    • MPMoviePlayerDidExitFullscreenNotification
    • 再生が停止しないことに注意してください
  • 映画が最後に到達する

    • MPMoviePlayerPlaybackDidFinishNotificationMPMoviePlayerPlaybackDidFinishReasonUserInfoKeyに設定してMPMovieFinishReasonPlaybackEnded
    • この通知からMoviePlayerControllerインスタンスでsetFullscreen:NO animated:YESを呼び出すと、WillExitおよびDidExit通知を受け取ります。
    • ユーザーが[完了]または[全画面表示を終了]ボタンを押しても、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];
}
66
Art Gillespie

はい。それは素晴らしいことです。上記の通知は本当にあります...

ただし、MPMoviePlayerPlaybackWillFinishNotificationはなぜありません!!!それは本当に問題です。

ムービープレーヤーをモーダルとして呼び出す場合(presentViewController/presentModalViewController/presentVideoControllerを使用する次のメソッドに関係なく)、. fullScreen = YESを定義した場合、呼び出しは想定されていませんMPMoviePlayerWillExitFullscreenNotification notification まったく(明らかに、フルスクリーンから出入りすることは考慮されていないため、コントローラーを表示/非表示にするだけです)。

しかし、ビデオが終了して閉じようとしているという通知は実際にはありません。 (他の可能な状況に加えて)却下の移行が始まる瞬間をとらえるために必要です。 (もちろん、遷移はMPMoviePlayerPlaybackDidFinishNotificationが呼び出される前に開始されます)。また、同時に、以前に表示されたコントローラーのapplication:supportedInterfaceOrientationsForWindow:が通知の前に呼び出され、現在のコントローラーが既に別の方向で表示されている必要があることをAppDelegateに伝える方法はありません。

したがって、私のビデオはフルスクリーンであり、コントロールも表示されていないため(これは一種のイントロなので、終了するまでです)私の解決策は、すべての短い目盛り(0.1秒)をチェックするタイマーを用意することでした)ビデオの現在の位置です ...そしてそれは終わりに近づいています、そしてこれは私自身の通知の瞬間です。

0
Agat