在 SwiftUI 中监听 AVPlayer timeControlStatus 变化

问题描述 投票:0回答:2

因此尝试在 SwiftUI 中实现 AVPlayer 的简单观察者。我已经添加了被触发的观察者,但还没有弄清楚如何/在哪里实现

observeValue
,按照Apple文档:https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/responding_to_playback_state_changes

到目前为止,我的 AVPlayer 类如下:

class Player: AVPlayer, ObservableObject {

    @Published var isPlaying: Bool = false

    static var shared = AVPlayer()
    static var episodeId: Int?

    static func playItem(at itemURL: String, episodeId: Int) {
        let url = URL(string: itemURL)
        Player.shared = AVPlayer(url: url!)
        Player.episodeId = episodeId
        Player.shared.addObserver(self.shared, forKeyPath: "timeControlStatus", options: [.old, .new], context: nil)
    }
}

所以问题是我应该在哪里实现它才能发挥作用:

override func observeValue(forKeyPath keyPath: String?,
                           of object: Any?,
                           change: [NSKeyValueChangeKey : Any]?,
                           context: UnsafeMutableRawPointer?) {
    if Player.shared.timeControlStatus == .playing {
        // Set @Published isPlaying to true
    }
}
ios swift swiftui avplayer
2个回答
2
投票

它可以像下面这样(不要使用

static
,在这种情况下不需要它,无论如何你都需要实例来使用
@ObservedObject

当然不是最终的

Player
,但是进化的方向应该是明确的:

class Player: AVPlayer, ObservableObject {

    @Published var isPlaying: Bool = false

    private var playerContext = 0

    var player: AVPlayer? = nil
    var episodeId: Int?

    func playItem(at itemURL: String, episodeId: Int) {
        guard let url = URL(string: itemURL) else { return }

        // cleanup for previous player
        self.player?.removeObserver(self, forKeyPath: "timeControlStatus")

        // setup new player
        let newPlayer = AVPlayer(url: url)
        newPlayer.addObserver(self, forKeyPath: "timeControlStatus", options: [.old, .new], context: &playerContext)

        self.player = newPlayer
        self.episodeId = episodeId
    }

    override func observeValue(forKeyPath keyPath: String?,
                               of object: Any?,
                               change: [NSKeyValueChangeKey : Any]?,
                               context: UnsafeMutableRawPointer?) {

        guard context == &playerContext else { // give super to handle own cases
               super.observeValue(forKeyPath: keyPath,
                       of: object,
                       change: change,
                       context: context)
               return
        }
        if self.player?.timeControlStatus == .playing {
            self.isPlaying = true
        }
    }
}

0
投票

https://developer.apple.com/documentation/combine/performing-key-value-observing-with-combine所述,您可以创建一个

combine
监听器

statusObserver = player.publisher(for: \.timeControlStatus)
    .receive(on: DispatchQueue.main)
    .sink { newStatus in
        isPlaying = newStatus == .playing
    }

其中

isPlaying: Bool
statusObserver: AnyCancellable?
在我看来是私有
@State
属性。

© www.soinside.com 2019 - 2024. All rights reserved.