KVO时iOS 11 AVPlayer崩溃 [英] iOS 11 AVPlayer crash when KVO

查看:633
本文介绍了KVO时iOS 11 AVPlayer崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 AVPlayer 播放远程视频时,我遇到了一个奇怪的崩溃。从 Fabric 上的崩溃日志开始,应用程序崩溃在系统线程上( com.apple.avfoundation.playerlayer.configuration )。崩溃日志如下:

I got a weird crash when using AVPlayer to play a remote video. From the crash log on Fabric, the App crash on system thread (com.apple.avfoundation.playerlayer.configuration). The crash log is below:

Crashed: com.apple.avfoundation.playerlayer.configuration
0  libsystem_kernel.dylib         0x1839ac2e8 __pthread_kill + 8
1  libsystem_pthread.dylib        0x183ac12f8 pthread_kill$VARIANT$mp + 396
2  libsystem_c.dylib              0x18391afbc abort + 140
3  libsystem_malloc.dylib         0x1839e3ce4 szone_size + 634
4  QuartzCore                     0x187ed75e8 -[CALayer dealloc] + 72
5  QuartzCore                     0x187e75d90 CA::Transaction::commit() + 1052
6  AVFoundation                   0x18973b4a8 -[AVPlayerLayer observeValueForKeyPath:ofObject:change:context:] + 684
7  Foundation                     0x1847a2894 NSKeyValueNotifyObserver + 304
8  Foundation                     0x1847bc364 -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] + 204
9  Foundation                     0x1847bc13c -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] + 124
10 AVFoundation                   0x189760714 -[AVPlayer addObserver:forKeyPath:options:context:] + 204
11 AVFoundation                   0x189890414 -[AVKVODispatcher startObservingValueAtKeyPath:ofObject:options:usingBlock:] + 136
12 AVFoundation                   0x18989189c -[AVKVODispatcher(LegacyCallbackMethod) startObservingObject:weakObserver:forKeyPath:options:context:] + 152
13 AVFoundation                   0x18973aef4 -[AVPlayerLayer _startObservingPlayer:] + 328
14 libdispatch.dylib              0x183816a54 _dispatch_call_block_and_release + 24
15 libdispatch.dylib              0x183816a14 _dispatch_client_callout + 16
16 libdispatch.dylib              0x18382096c _dispatch_queue_serial_drain$VARIANT$mp + 528
17 libdispatch.dylib              0x1838212fc _dispatch_queue_invoke$VARIANT$mp + 340
18 libdispatch.dylib              0x183821d20 _dispatch_root_queue_drain_deferred_wlh$VARIANT$mp + 404
19 libdispatch.dylib              0x18382a03c _dispatch_workloop_worker_thread$VARIANT$mp + 644
20 libsystem_pthread.dylib        0x183abef1c _pthread_wqthread + 932
21 libsystem_pthread.dylib        0x183abeb6c start_wqthread + 4

注意:所有崩溃发生在 iOS11

Notice: all of the crash happened on iOS11

有人知道为什么会发生此次崩溃吗?

Does anybody have an idea why this crash occurred?

推荐答案

从堆栈跟踪中,我注意到 AVPlayerLayer observeValueForKeyPath:ofObject:change:context:似乎是导致问题的原因。因此,我相信您必须为 AVPlayer 实施KVO。

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. 使用新的Key-Value-Observing iOS 11 API,你有放宽要求,但这些不必取消观察的要求仅适用于以下条件:

  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:




放宽键值观察注销要求

•对象必须使用KVO自动调整,而不是手动
调用-will和-didChangeValueForKey :(即它不应该从+ automaticNotifiesObserversForKey返回NO
)。

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

•对象不得为
覆盖内部KVO状态的(私有)访问者。

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

参见这里看到这个在新API中使用旧API实现 addObserver removeObserver 方法。请注意,文档对新API的帮助不大,因为它仍然基于旧的KVO实现。但是,正如您所看到的那样,取消注册会在 deinit 上自动发生。

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 为KVO支持隐藏了 AVPlayer 的实现(它是一个私有框架),但这些宽松的要求很可能不适用于 AVPlayer 。在2018年代码片段使用 AVPlayer 使用新的KVO API,但仍在 deinit 方法中取消注册(确认怀疑 AVPlayer 不符合新API的轻松取消注册要求。)

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).

另一种解释是取消注册发生在 deinit ,但不一定在主线程中完成。这对于 AVPlayer KVO很重要。

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


  1. 这个原因重要的是可以从 docs 中找到:

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




一般状态观察:您应该在
主线程上注册和取消注册KVO更改通知。如果在另一个线程上进行更改,这可以避免收到部分
通知的可能性。

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.

总之,如果使用新API为 AVPlayer 实施KVO,您需要在完成后明确取消注册。另外,将注册和取消注册代码包装在 DispatchQueue.main.async {} 或类似的变体中。

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假设您的密钥路径有效(只需确保它们是动态属性)。

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

这篇关于KVO时iOS 11 AVPlayer崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆