I am trying to set an observer for the currentItem
of the AVQueueplayer
but I get an error called EXC_BAD_ACCESS
. Can someone help me please? Thanks for your attention. I’m looking forward to your reply. Here is my code:
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, which is struct, cannot be used KVO observer. You can to use Coordinator
as observer.
Here is modified code with possible approach:
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>) {
}
}