我有一个带有视图的 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)
}
}
我认为这可能是因为您只在 currentItem 上设置了观察者。如果可以将它放在所有项目上而不一遍又一遍地删除和添加观察者,我将需要调查自己。
您可以像这样设置 actionAtItemEnd 属性。
player.actionAtItemEnd = .pause
在每个项目结束时自动暂停。
然后听听这个的可观察属性:
let cancellables = Set<AnyCancellable>()
player.publisher(for: \.actionAtItemEnd).sink(receiveValue: { _ in
print("Item ended")
}).store(in: &cancellables)
希望这有帮助。
观察者仅在视图出现时被添加到当前项目。
您可以在将每个项目传递给 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)
}