首页 > 解决方案 > 如何在队列播放器的 currentItem 上设置观察者?

问题描述

我正在尝试为currentItemof设置一个观察者,AVQueueplayer但我收到一个名为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>) {
      
}
}

标签: swiftswiftuiavplayeravkitavqueueplayer

解决方案


Representable,即struct,不能用于KVO观察者。您可以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>) {

    }
}

推荐阅读