如何在队列玩家的 currentItem 上设置观察者?

How to set an observer on the queue player's currentItem?

我正在尝试为 AVQueueplayercurrentItem 设置观察者,但我收到一个名为 EXC_BAD_ACCESS 的错误。有谁可以帮助我吗?感谢您的关注。我期待着您的回复。这是我的代码:

struct VideoPlayerS : UIViewControllerRepresentable {
        
var work : WorkoutDeS
@Binding var player : AVQueuePlayer
var playerLayer = AVPlayerLayer()
    
public func makeUIViewController(context: Context) -> AVPlayerViewController {
    let items = [
        
        AVPlayerItem(url: URL(fileURLWithPath: String(work.url1))),
    AVPlayerItem(url: URL(fileURLWithPath: String(work.url2)))
        
    ]
   let player = AVQueuePlayer(items: items)
       let controller = AVPlayerViewController()

       DispatchQueue.main.async {
          self.player = player
       }
    controller.player = player
    controller.videoGravity = .resizeAspectFill

    
    

    
    player.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { _ in
        self.player.seek(to: CMTime.zero)
        self.player.play()
    }
    player.play()
    
    
    player.currentItem?.addObserver(AVQueuePlayer(), forKeyPath: "status", options: NSKeyValueObservingOptions(), context: nil)
    
   
    func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
       
           
           
       if keyPath == "status" {
           print("Hello")
            
               player.currentItem?.removeObserver(AVQueuePlayer(), forKeyPath: "status")
           
       
       }
       }

    
    return controller
}






func rewindVideo(notification: Notification) {
    playerLayer.player?.seek(to: .zero)
}

public func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayerS>) {
      
}
}

Representable,是struct,不能用KVO observer。您可以使用 Coordinator 作为观察者。

这里是修改后的代码,可能的方法是:

struct VideoPlayerS : UIViewControllerRepresentable {

    var work : WorkoutDeS
    @Binding var player : AVQueuePlayer
    var playerLayer = AVPlayerLayer()

    public func makeUIViewController(context: Context) -> AVPlayerViewController {
        let items = [

            AVPlayerItem(url: URL(fileURLWithPath: String(work.url1))),
            AVPlayerItem(url: URL(fileURLWithPath: String(work.url2)))

        ]
        let player = AVQueuePlayer(items: items)
        let controller = AVPlayerViewController()

        DispatchQueue.main.async {
            self.player = player
        }
        controller.player = player
        controller.videoGravity = .resizeAspectFill

        player.actionAtItemEnd = .none
        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player.currentItem, queue: .main) { _ in
            self.player.seek(to: CMTime.zero)
            self.player.play()
        }

        player.currentItem?.addObserver(context.coordinator, forKeyPath: "status", options: [.new], context: nil)

        player.play()
        return controller
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(owner: self)
    }

    class Coordinator: NSObject {
        var owner : VideoPlayerS

        init(owner: VideoPlayerS) {
            self.owner = owner
        }

        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            guard let item = object as? AVPlayerItem else { return }

            if keyPath == "status" {
                print("Hello")
                item.removeObserver(self, forKeyPath: "status")
            }
        }
    }

    func rewindVideo(notification: Notification) {
        playerLayer.player?.seek(to: .zero)
    }

    public func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VideoPlayerS>) {

    }
}