如何拦截在AVPlayerViewController中点击完成按钮?

Sim*_*mon 18 objective-c ios xcode6 ios8

我创建了一个AVPlayerViewController和一个附加AVPlayerviewDidAppear一个自定义的方法UIViewController.但是,当我按下"完成"按钮时,我的自定义视图控制器会自动关闭.

我想拦截这个动作,以便使用我自己的放松塞格,但我不知道该怎么做.我找到了MPMoviePlayerViewController但不是的例子AVPlayerViewController.

我找到的代码MPMoviePlayerViewController如下:

- (void)playVideo:(NSString *)aVideoUrl {
    // Initialize the movie player view controller with a video URL string
    MPMoviePlayerViewController *playerVC = [[[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:aVideoUrl]] autorelease];

    // Remove the movie player view controller from the "playback did finish" notification observers
    [[NSNotificationCenter defaultCenter] removeObserver:playerVC
                                                name:MPMoviePlayerPlaybackDidFinishNotification
                                              object:playerVC.moviePlayer];

    // Register this class as an observer instead
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(movieFinishedCallback:)
                                                 name:MPMoviePlayerPlaybackDidFinishNotification
                                               object:playerVC.moviePlayer];

    // Set the modal transition style of your choice
    playerVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

    // Present the movie player view controller
    [self presentModalViewController:playerVC animated:YES];

    // Start playback
    [playerVC.moviePlayer prepareToPlay];
    [playerVC.moviePlayer play];
}

- (void)movieFinishedCallback:(NSNotification *)aNotification {
    // Obtain the reason why the movie playback finished
    NSNumber *finishReason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];

    // Dismiss the view controller ONLY when the reason is not "playback ended"
    if ([finishReason intValue] != MPMovieFinishReasonPlaybackEnded) {
        MPMoviePlayerController *moviePlayer = [aNotification object];

        // Remove this class from the observers
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:MPMoviePlayerPlaybackDidFinishNotification
                                                      object:moviePlayer];

        // Dismiss the view controller
        [self dismissModalViewControllerAnimated:YES];
    }
}
Run Code Online (Sandbox Code Playgroud)

我向Apple询问了这个问题,他们回复如下:

感谢您与Apple开发人员技术支持(DTS)联系.我们的工程师已经审核了您的请求,并得出结论,鉴于当前出货的系统配置,没有支持的方法来实现所需的功能.

dev*_*dev 5

我将AVPlayerViewController子类化,并发布了来自viewWillDisappear的通知,以指示解雇AVPlayerViewController.

- (void) viewWillDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] postNotificationName:kPlayerViewDismissedNotification object:nil];
    [super viewWillDisappear:animated];
}
Run Code Online (Sandbox Code Playgroud)

这可能不是100%正确(因为如果你有另一个视图显示在AVPlayerViewController上会失败),但它对我有用,因为AVPlayerViewController总是在堆栈的顶部.

  • 根据Apple Docs:**不要继承AVPlayerViewController.覆盖此类的方法不受支持并导致未定义的行为.**来源:https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVPlayerViewController_Class/ (15认同)
  • 如果我不想继承AVPlayerViewController(如Apple建议:不要继承AVPlayerViewController.覆盖此类的方法不受支持并导致未定义的行为.这里:https://developer.apple.com/library/prerelease/ios /documentation/AVFoundation/Reference/AVPlayerViewController_Class/index.html)有没有办法获得通知? (2认同)

Zyp*_*rax 5

Apple没有提供内置方式来处理Done按钮这一事实令人失望.

我不想从AVPlayerViewController继承,因为Apple不支持它,并且可能会在下一个iOS更新中打开一堆蠕虫.

我的解决方法是每200毫秒启动一次计时器并检查以下情况:

if (playerVC.player.rate == 0 &&
   (playerVC.isBeingDismissed || playerVC.nextResponder == nil)) {
  // Handle user Done button click and invalidate timer
}
Run Code Online (Sandbox Code Playgroud)

播放器的rate属性为0表示视频不再播放.如果视图控制器被解雇或已被解雇,我们可以安全地假设用户单击了完成按钮.


Mar*_*gan 5

我通过保留对AVPlayerViewController实例的弱引用并使用计时器将引用更改为nil的计时器来解决。

private weak var _playerViewController : AVPlayerViewController? // global reference
    ...
    ...
    let playerController = AVPlayerViewController() // local reference
    ...
    self.present(playerController, animated: true) { [weak self] in
        playerController.player?.play()
        self?._playerViewController = playerController
        // schedule a timer to intercept player dismissal
        Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] (timer) in
        if self?.playerViewController == nil {
            // player vc dismissed
            timer.invalidate()
        }
}
Run Code Online (Sandbox Code Playgroud)