swift 如何使用AVPlayerViewController检测播放控件显示上的切换?

monwx1rj  于 2023-10-15  发布在  Swift
关注(0)|答案(2)|浏览(109)

我想知道是否可以检测播放控件何时从AVPlayerViewController视图中出现或消失。我试图在播放器上添加一个UI元素,它必须跟随播放控件显示。仅在显示控件时出现,否则消失
我似乎没有找到任何价值,我可以观察到AVPlayerViewController实现这一点,也没有任何回调或委托方法。
我的项目在Swift中。

tquggr8v

tquggr8v1#

观察和响应播放变化的一种简单方法是使用键值观察(KVO)。在您的情况下,请观察AVPlayer的timeControlStatusrate属性。
例如:

{
  // 1. Setup AVPlayerViewController instance (playerViewController)

  // 2. Setup AVPlayer instance & assign it to playerViewController

  // 3. Register self as an observer of the player's `timeControlStatus` property

  // 3.1. Objectice-C
  [player addObserver:self
           forKeyPath:@"timeControlStatus"
              options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew // NSKeyValueObservingOptionOld is optional here
              context:NULL];

  // 3.2. Swift
  player.addObserver(self,
                     forKeyPath: #keyPath(AVPlayer.timeControlStatus),
                     options: [.old, .new], // .old is optional here
                     context: NULL)
}

要获得状态更改的通知,需要实现-observeValueForKeyPath:ofObject:change:context:方法。每当timeControlStatus值更改时,就会调用此方法。

// Objective-C
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary <NSKeyValueChangeKey, id> *)change
                       context:(void *)context
{
  if ([keyPath isEqualToString:@"timeControlStatus"]) {
    // Update your custom UI here depend on the value of `change[NSKeyValueChangeNewKey]`:
    // - AVPlayerTimeControlStatusPaused
    // - AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
    // - AVPlayerTimeControlStatusPlaying
    AVPlayerTimeControlStatus timeControlStatus = (AVPlayerTimeControlStatus)[change[NSKeyValueChangeNewKey] integerValue];
    // ...

  } else {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
}

// Swift
override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?)
{
  if keyPath == #keyPath(AVPlayer.timeControlStatus) {
    // Deal w/ `change?[.newKey]`
  } else {
    super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
  }
}

最后一个最重要的步骤,当你不再需要观察者时,记得删除它,一般在-dealloc

[playerViewController.player removeObserver:self forKeyPath:@"timeControlStatus"];

顺便说一下,你也可以观察AVPlayer的rate属性,导致-play相当于将rate的值设置为1.0,而-pause相当于将rate的值设置为0.0。
但在你的情况下,我认为timeControlStatus更有意义。
有一个官方的DOC供进一步阅读(但只是“准备玩”,“失败”和“未知”状态,在这里无用):"Responding to Playback State Changes"
希望有帮助。

hivapdat

hivapdat2#

设法找到一些工作(至少对iOS)的基础上对另一个职位的评论。它可能不适用于所有平台,可能不适用于所有平台。
创建一个AVPlayerViewController子类,并在它的一个子视图上设置一个观察器,检查hidden属性的更改。试图以一种避免显式使用任何标记为私有的东西的方式来避免任何应用程序商店问题。下面的代码为任何人寻找同样的,请让我知道,如果你发现任何更好的

import AVKit

protocol CustomAVPlayerViewControllerDelegate: AnyObject {
    
    func playbackControlsChanged(visible: Bool)
}

class CustomAVPlayerViewController: AVPlayerViewController {
    
    private var viewToMonitor: UIView? = nil
    private var previousValue = true
    
    public weak var customDelegate: CustomAVPlayerViewControllerDelegate? = nil
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let container = view.subviews.first
        viewToMonitor = container?.subviews.last
        previousValue = viewToMonitor?.isHidden ?? true
        
        viewToMonitor?.addObserver(self, forKeyPath: "hidden", context: nil)
    }
    
    deinit {
        viewToMonitor?.removeObserver(self, forKeyPath: "hidden")
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        // Check if its the correct element and avoid double trigger
        if keyPath == "hidden", let v = viewToMonitor, previousValue != v.isHidden {
            previousValue = v.isHidden
            customDelegate?.playbackControlsChanged(visible: !v.isHidden)
        }
    }
}

相关问题