iOS 11 AVPlayer crash when KVO

元气小坏坏 提交于 2019-12-03 12:12:30

From your stack trace, I noticed that AVPlayerLayer observeValueForKeyPath:ofObject:change:context: seems to be the cause of your issue. Hence I believe you must be implementing KVO for AVPlayer.

In which case, note two points:

  1. With the new Key-Value-Observing iOS 11 API you have relaxed requirements, however these requirements for not having to deregister from observations only apply under the following conditions:

Relaxed Key-Value Observing Unregistration Requirements

• The object must be using KVO autonotifying, rather than manually calling -will and -didChangeValueForKey: (i.e. it should not return NO from +automaticallyNotifiesObserversForKey:).

• The object must not override the (private) accessors for internal KVO state.

See here to see this being implemented in the new API with the old API addObserver and removeObserver methods. Note that the documentation is not very helpful for the new API as yet because it still is based on the old KVO implementation. But, as you can see deregistering happens automatically on deinit.

AVFoundation hides the implementation of AVPlayer for KVO support (it's a private framework), but it is likely that these relaxed requirements do not apply for AVPlayer. This code snippet from Apple in 2018, uses AVPlayer with the new KVO API, but still deregisters in a deinit method (confirming suspicions that AVPlayer does not meet the relaxed unregistration requirements for the new API).

Another explanation is that deregistering happens in deinit, but not necessarily done in the main thread. This is important for AVPlayer KVO.

  1. The reason this is important can be found from the docs:

General State Observations: You should register and unregister for KVO change notifications on the main thread. This avoids the possibility of receiving a partial notification if a change is being made on another thread.

In summary, if implementing KVO for AVPlayer with the new API, you need to explicitly unregister when you're done. Also, wrap your registering and unregistering code inside a DispatchQueue.main.async { } or similar variant.

I have assumed here that your key path is valid (just make sure they are dynamic properties).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!