我在使用时遇到了奇怪的崩溃AVPlayer播放远程视频。从崩溃登录Fabric,应用程序在系统线程上崩溃(com.apple.avfoundation.playerlayer.configuration)。崩溃日志如下:
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
有人知道为什么会发生这次事故吗?
从你的堆栈跟踪中,我注意到AVPlayerLayer observeValueForKeyPath:ofObject:change:context:
似乎是你的问题的原因。因此我相信你必须实施 KVOAVPlayer
.
在这种情况下,请注意两点:
- 借助新的键值观察 iOS 11 API,您可以放宽要求 https://developer.apple.com/library/content/releasenotes/Foundation/RN-Foundation/index.html,但是,这些不必从观察中注销的要求仅适用于以下条件:
放宽键值观察注销要求
• 对象必须使用 KVO 自动通知,而不是手动通知
调用 -will 和 -didChangeValueForKey: (即它不应该返回 NO
来自+automaticallyNotifyObserversForKey:)。
• 该物体不得
覆盖内部 KVO 状态的(私有)访问器。
See here https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/NSObject.swift#L159看看这在新 API 和旧 API 中实现addObserver
and removeObserver
方法。请注意,该文档对于新 API 还没有太大帮助,因为它仍然基于旧的 KVO 实现。但是,正如您所看到的,取消注册会自动发生deinit
.
AVFoundation
隐藏了执行AVPlayer
用于 KVO 支持(它是一个私有框架),但这些宽松的要求可能不适用于AVPlayer
. This https://developer.apple.com/library/content/samplecode/AVFoundationPiPPlayer/Listings/AVFoundationPiPPlayer_PlayerViewController_swift.html2018 年 Apple 的代码片段,使用AVPlayer
使用新的 KVO API,但仍会在deinit
方法(证实怀疑AVPlayer
不满足新 API 宽松的注销要求)。
另一种解释是注销发生在deinit
,但不一定在主线程中完成。这对于AVPlayer
KVO.
- 这一点很重要的原因可以从docs https://developer.apple.com/documentation/avfoundation/avplayer:
一般状态观察:您应该在
主线程。这避免了收到部分信息的可能性
如果在另一个线程上进行更改,则发出通知。
总之,如果实现 KVOAVPlayer
使用新的 API,您需要明确地完成后取消注册。另外,将您的注册和取消注册代码包装在DispatchQueue.main.async { }
或类似的变体。
我在这里假设您的关键路径是有效的(只需确保它们是动态属性)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)