I get random crashes (which I can't reproduce on devices I own) in my app with exception:
Cannot remove an observer Foundation.NSKeyValueObservation 0xaddress for the key path "readyForDisplay" from AVPlayerLayer 0xaddress because it is not registered as an observer.
This happens when I deallocate a UIView which contains AVPlayerLayer.
My init:
private var playerLayer : AVPlayerLayer { return self.layer as! AVPlayerLayer }
init(withURL url : URL) {
...
self.asset = AVURLAsset(url: url)
self.playerItem = AVPlayerItem(asset: self.asset)
self.avPlayer = AVPlayer(playerItem: self.playerItem)
super.init(frame: .zero)
...
let avPlayerLayerIsReadyForDisplayObs = self.playerLayer.observe(\AVPlayerLayer.isReadyForDisplay, options: [.new]) { [weak self] (plLayer, change) in ... }
self.kvoPlayerObservers = [..., avPlayerLayerIsReadyForDisplayObs, ...]
...
}
My deinit where exception is thrown:
deinit {
self.kvoPlayerObservers.forEach { $0.invalidate() }
...
NotificationCenter.default.removeObserver(self)
}
According to Crashlytics it happens on iOS 11.4.1 on different iPhones.
The code leading to deinit
is pretty simple:
// Some UIViewController context.
self.viewWithAVLayer?.removeFromSuperview()
self.viewWithAVLayer = nil
I would appreciate any thoughts on why this happens.
I have seen this bug but it doesn't seem to be the cause for me.
EDIT 1:
Additional info for posterity. On iOS 10 if I don't invalidate I get reproducible crash on deinit. On iOS 11 it works without invalidation (not checked yet if crash disappears if I don't invalidate and let observers to be deinit
ed with my class).
EDIT 2:
Additional info for posterity: I have also found this Swift bug which might be related - SR-6795.