AvPlayer 上的观察者仅适用于第一项

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

我有一个带有视图的 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)
    }
    
    
}
swift swiftui avplayer avkit avqueueplayer
2个回答
0
投票

我认为这可能是因为您只在 currentItem 上设置了观察者。如果可以将它放在所有项目上而不一遍又一遍地删除和添加观察者,我将需要调查自己。

您可以像这样设置 actionAtItemEnd 属性。

player.actionAtItemEnd = .pause
在每个项目结束时自动暂停。

然后听听这个的可观察属性:

let cancellables = Set<AnyCancellable>()

player.publisher(for: \.actionAtItemEnd).sink(receiveValue: { _ in
   print("Item ended")
}).store(in: &cancellables)

希望这有帮助。


0
投票

观察者仅在视图出现时被添加到当前项目。

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

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

在选择器方法中,您可以进行设置和清理观察者。

@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)
}
© www.soinside.com 2019 - 2024. All rights reserved.