swift AvPlayer上的观察者仅对第一项有效

9w11ddsr  于 2023-03-22  发布在  Swift
关注(0)|答案(2)|浏览(154)

我有一个SwiftUi应用程序的视图,我想从远程播放一系列视频。我用的是AVQueuePlayer。
在任何再现结束时,我希望在从暂停阵列中定义的暂停之后播放下一个视频。
这段代码只在第一个播放的项目后工作,然后观察者不拦截任何东西。有什么建议吗?

struct ExercisesPlay: View {
    
    @State var urls: [URL]
    @State var pauses: [Int]
    
    var player: AVQueuePlayer
    
    @State var showToast: Bool = false
    
    init(urls: [URL], pauses: [Int]) {
        self.urls = urls
        self.pauses = pauses
        
        var array: [AVPlayerItem] = []
        urls.forEach { URL in
            array.append(AVPlayerItem(url: URL))
        }
        self.player = AVQueuePlayer(items: array)
    }
    
    
    var body: some View {
        VideoPlayer(player:player)
            .onAppear{
                player.play()
                addObserver()
            }
            .onDisappear{
                removeObserver()
            }
            .toast(message: LocalizedStringKey("Pause").stringValue()!,
                   isShowing: self.$showToast, duration: Toast.long)
        
    }
    
    func addObserver() {
        NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue:nil ) { notif in

            self.showToast.toggle()
            
            if(!pauses.isEmpty){
                
                print(player.currentItem)
                
                player.pause()
                
                DispatchQueue.main.asyncAfter(deadline: (.now() + DispatchTimeInterval.seconds(pauses.first!))) {
                    player.seek(to: .zero)
                    player.play()
                    pauses.remove(at: 0)
                    
                }
            }
        }
    }
    
    func removeObserver() {
        NotificationCenter.default.removeObserver(self,name: .AVPlayerItemDidPlayToEndTime, object: nil)
    }
    
    
}
7kjnsjlb

7kjnsjlb1#

观察者仅在视图出现时添加到当前项。
您可以在将每个项目传递给AVQueuePlayer之前为其添加一个观察者。如果包含对该对象的引用,则可以在以后更轻松地删除观察者。

urls.forEach { URL in
    let item = AVPlayerItem(url: URL)
    NotificationCenter.default.addObserver(self, selector: #selector(itemFinishedPlaying), name: .AVPlayerItemDidPlayToEndTime, object: item)
    array.append(item)
}

在selector方法中,可以设置和清理观察点。

@objc private func itemFinishedPlaying(_ notification: NSNotification) {
NotificationCenter.default.removeObserver(self, name: notification.name, object: notification.object)

// additional code you want to perform goes here

}

如果您想在视图消失时清除所有的观察者,您可以遍历排队的项。

for item in player.items() {
    NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: item)
}
elcex8rz

elcex8rz2#

我想这可能是因为你只在currentItem上设置了观察者。我需要自己调查一下,是否有可能把它放在所有的项目上,而不需要一遍又一遍地删除和添加观察者。
你可以设置监听currentItem的每一次改变。然后每当一个项目被改变时,你可以暂停播放器x秒,然后重新启动播放器。

let cancellables = Set<AnyCancellable>()

player.publisher(for: \.currentItem).sink(receiveValue: { _ in
   print("New currentItem")
}).store(in: &cancellables)

希望这个有用。

相关问题