简体   繁体   English

KVO导致iOS 11 AVPlayer崩溃

[英]iOS 11 AVPlayer crash when KVO

I got a weird crash when using AVPlayer to play a remote video. 使用AVPlayer播放远程视频时出现了奇怪的崩溃。 From the crash log on Fabric , the App crash on system thread ( com.apple.avfoundation.playerlayer.configuration ). Fabric上的崩溃日志中,应用程序在系统线程( 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

Notice: all of the crash happened on iOS11 注意:所有崩溃事件均发生在iOS11上

Does anybody have an idea why this crash occurred? 有人知道为什么发生此崩溃吗?

From your stack trace, I noticed that AVPlayerLayer observeValueForKeyPath:ofObject:change:context: seems to be the cause of your issue. 从您的堆栈跟踪中,我注意到AVPlayerLayer observeValueForKeyPath:ofObject:change:context:似乎是造成您问题的原因。 Hence I believe you must be implementing KVO for AVPlayer . 因此,我相信您必须为AVPlayer实现KVO。

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: 使用新的键值观察iOS 11 API,您可以放宽要求 ,但是这些不必从观察中注销的要求仅在以下情况下适用:

Relaxed Key-Value Observing Unregistration Requirements 宽松的键值观察取消注册要求

• The object must be using KVO autonotifying, rather than manually calling -will and -didChangeValueForKey: (ie it should not return NO from +automaticallyNotifiesObserversForKey:). •对象必须使用KVO自动通知,而不是手动调用-will和-didChangeValueForKey:(即,它不应从+ automaticallyNotifyObserversForKey:返回NO)。

• The object must not override the (private) accessors for internal KVO state. •对象不得覆盖内部KVO状态的(专用)访问器。

See here to see this being implemented in the new API with the old API addObserver and removeObserver methods. 请参见此处,以了解如何使用旧的API addObserverremoveObserver方法在新的API中实现此功能。 Note that the documentation is not very helpful for the new API as yet because it still is based on the old KVO implementation. 请注意,该文档对于新API仍然不是很有帮助,因为它仍然基于旧的KVO实现。 But, as you can see deregistering happens automatically on deinit . 但是,如您所见,注销会在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 . AVFoundation隐藏了AVFoundation支持的AVPlayer实现(这是一个私有框架),但是这些宽松的要求很可能不适用于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). Apple于2018年发布的代码段将AVPlayer与新的KVO API结合使用,但仍以deinit方法注销(确认怀疑AVPlayer不满足新API宽松的注销要求)。

Another explanation is that deregistering happens in deinit , but not necessarily done in the main thread. 另一个解释是注销发生在deinit ,但不一定在主线程中完成。 This is important for AVPlayer KVO. 这对于AVPlayer KVO很重要。

  1. The reason this is important can be found from the docs : 重要的原因可以在docs中找到:

General State Observations: You should register and unregister for KVO change notifications on the main thread. 一般状态观察:您应该在主线程上注册和注销KVO更改通知。 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. 总而言之,如果使用新的API为AVPlayer实施KVO,则需要在完成后显式注销。 Also, wrap your registering and unregistering code inside a DispatchQueue.main.async { } or similar variant. 另外,将您的注册和注销代码包装在DispatchQueue.main.async { }或类似的变量中。

I have assumed here that your key path is valid (just make sure they are dynamic properties). 我在这里假设您的密钥路径是有效的(只需确保它们是动态属性)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM