向玩家添加观察者时出错
Error while adding an observer to a player
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'An instance 0x1702076f0
of class AVPlayerItem was deallocated while key value observers were
still registered with it. Current observation info:
(
(.<)NSKeyValueObservance 0x174846360: Observer: 0x174846210, Key path:
loadedTimeRanges, Options: Context:
0x0, Property: 0x1748462d0> )'
这是我在将 currentItem.loadedTimeRanges 观察器添加到我的 AVPlayer
后收到的错误
player = AVPlayer(url: videoUrl!)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = postVideoView.frame
playerLayer.frame.size.width = UIScreen.main.bounds.width
self.postVideoView.layer.addSublayer(playerLayer)
player?.play()
player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: nil, using: { (_) in
DispatchQueue.main.async {
self.player?.seek(to: kCMTimeZero)
self.player?.play()
}
})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
//this is when the player is ready and rendering frames
if keyPath == "currentItem.loadedTimeRanges" {
if let duration = player?.currentItem?.duration {
let seconds = CMTimeGetSeconds(duration)
let secondsText = Int(seconds) % 60
let minutesText = String(format: "%02d", Int(seconds) / 60)
videoLengthLabel.text = "\(minutesText):\(secondsText)"
}
}
}
你在哪里打电话给removeObserver
?目前看起来,如果您的顶级代码创建了一个新玩家并添加了一个观察者。如果这被调用两次,第一个实例中的观察者将仍然存在。因此,我希望顶部有以下行:
self.player?.removeObserver(self)
如果它没有被调用两次,代码中是否还有其他地方 self.player
被重新分配或解除分配?如果是这样,您应该首先调用 removeObserver
.
您还每次向 NotificationCenter 添加一个新的观察者。这应该只被调用一次或 removeObserver
在添加另一个之前。
您需要确保没有多次添加和删除观察者。所以最好的方法就是声明一个 bool 变量让我们说 var isObserverAdded = false.
添加观察者时检查此标志,如果未添加
if !isObserverAdded {
//Add your observer
isObserverAdded = true//Set this to true
}
删除观察者时检查标志是否已添加
if isObserverAdded {
//Add your observer
isObserverAdded = false//Set this to false
}
如果使用上面的检查,你将永远不会得到错误。
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x1702076f0 of class AVPlayerItem was deallocated while key value observers were still registered with it. Current observation info: (
(.<)NSKeyValueObservance 0x174846360: Observer: 0x174846210, Key path: loadedTimeRanges, Options: Context: 0x0, Property: 0x1748462d0> )'
这是我在将 currentItem.loadedTimeRanges 观察器添加到我的 AVPlayer
后收到的错误player = AVPlayer(url: videoUrl!)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = postVideoView.frame
playerLayer.frame.size.width = UIScreen.main.bounds.width
self.postVideoView.layer.addSublayer(playerLayer)
player?.play()
player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: nil, using: { (_) in
DispatchQueue.main.async {
self.player?.seek(to: kCMTimeZero)
self.player?.play()
}
})
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
//this is when the player is ready and rendering frames
if keyPath == "currentItem.loadedTimeRanges" {
if let duration = player?.currentItem?.duration {
let seconds = CMTimeGetSeconds(duration)
let secondsText = Int(seconds) % 60
let minutesText = String(format: "%02d", Int(seconds) / 60)
videoLengthLabel.text = "\(minutesText):\(secondsText)"
}
}
}
你在哪里打电话给removeObserver
?目前看起来,如果您的顶级代码创建了一个新玩家并添加了一个观察者。如果这被调用两次,第一个实例中的观察者将仍然存在。因此,我希望顶部有以下行:
self.player?.removeObserver(self)
如果它没有被调用两次,代码中是否还有其他地方 self.player
被重新分配或解除分配?如果是这样,您应该首先调用 removeObserver
.
您还每次向 NotificationCenter 添加一个新的观察者。这应该只被调用一次或 removeObserver
在添加另一个之前。
您需要确保没有多次添加和删除观察者。所以最好的方法就是声明一个 bool 变量让我们说 var isObserverAdded = false.
添加观察者时检查此标志,如果未添加
if !isObserverAdded {
//Add your observer
isObserverAdded = true//Set this to true
}
删除观察者时检查标志是否已添加
if isObserverAdded {
//Add your observer
isObserverAdded = false//Set this to false
}
如果使用上面的检查,你将永远不会得到错误。