包装 AVPlayer 行为时处理 AVPlayerLayer

Handling AVPlayerLayer when wrapping AVPlayer behaviour

我正在尝试将 AVPlayer 包装在我自己的 class 中,以便我可以提供更好的 API 以在我的整个应用程序中使用,因此我可以模拟玩家行为以进行测试其他对象(并且因为 AVPlayer KVO 使用起来非常难看!)。这是我尝试使用播放和暂停功能进行操作的简化模型:

protocol VideoPlayerProtocol {
    func play()
    func pause()
}

class AVPlayerWrapped: VideoPlayerProtocol {

    private let player = AVPlayer()

    init(playerItem: AVPlayerItem) {
        self.player.replaceCurrentItem(with: playerItem)
    }

    func play() {
        player.play()
    }

    func pause() {
        player.pause()
    }
}

我还有一个 PlayerView,它向视图添加了一个 AVPlayerLayer。在 Apple 文档中,这是通过提供 AVPlayer:

视图来设置的
class PlayerView: UIView {

    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }

    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    var player: AVPlayer? {
        get { playerLayer.player }
        set { playerLayer.player = newValue }
    }
}

问题是,当我设置一个 AVPlayerWrapped 对象时,为了在视图中显示回放,我需要将底层 AVPlayer 显示给 player 属性 PlayerView 这违背了我包裹玩家的目的。

有没有办法让我以某种方式使用 AVPlayerLayer 而我的 AVPlayerWrapped 不必透露其底层播放器?还是我采取了错误的方法?

非常感谢任何指导!

class AVPlayerWrapped: VideoPlayerProtocol {

    fileprivate let player = AVPlayer()

    init(playerItem: AVPlayerItem) {
        self.player.replaceCurrentItem(with: playerItem)
    }

    func play() {
        player.play()
    }

    func pause() {
        player.pause()
    }
}

extension AVPlayerLayer {
    func setPlayerWrapper(_ playerWrapped: AVPlayerWrapped) {
        player = playerWrapped.player
    }
}

class PlayerView: UIView {

    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }

    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    func setPlayerWrapper(_ playerWrapped: AVPlayerWrapped) {
        playerLayer.setPlayerWrapper(playerWrapped)
    }
}

我相信您的观点不需要 getter - 在我的实践中我没有使用过它。但是如果你这样做,你可以用一个关联的对象来做,但它比真正的要慢得多 属性 我建议你只在特殊情况下使用这种方法。