【发布时间】:2017-12-15 09:04:59
【问题描述】:
自从 iOS 11 发布以来,我遇到了偶发但频繁的崩溃,其特征如下:
Cannot remove an observer <CBPeripheral 0x1c010ef10> for the key path "delegate" from <CBPeripheral 0x1c010ef10> because it is not registered as an observer.
这发生在扫描蓝牙设备、稍后连接到其中一个设备以及最终清理整个过程的情况下。所有这些任务都在非主调度队列中执行,以减轻主线程的压力(以获得更流畅的 UI 体验)。自 iOS 9 天以来,这段代码一直在运行而没有发生任何事故,直到 iOS 11 发布后才开始崩溃。
到目前为止,我在网上找到的关于此行为的唯一参考资料是 Estimote SDK 的 this 和 this 帖子。这些参考表明,在不同的调度队列中 CBCentralManager 的并行实例可能会发生一些事情,但是,官方Programming Guide 中没有说明关于此事的特别注意事项。此外,Apple 员工 成员对another CoreBluetooth 问题的回复指出:
一般来说,iOS 11 对没有正确引用 CB 对象的应用程序的宽容度会降低...
听起来不太令人鼓舞。我尝试使用 XCode 及其配套工具分析应用程序并寻找潜在的泄漏,但这也没有说明太多。
有没有其他人遇到过类似的问题?关于如何解决它的任何建议?关于下一步在哪里挖掘的想法?
【问题讨论】:
-
自 iOS 11 以来我遇到了同样的事情,并且不确定原因或如何解决它。它也非常难以重现。
-
在与 Apple 员工的私人交流中,他建议在同一个线程中处理所有 CBCentral 活动,因为回调和其他消息事件向对象发送信号。显然,如果生成的对象(例如 CBPeripheral)在其他线程中被处理和释放,则所提到的信号可能会引用已释放的对象,因此会崩溃。不过,目前还没有明确的结论。
-
经过反复试验,我个人也得出了相同的结论,但我不想在这里写,直到我确认它已解决。这条知识应该以更易于搜索的方式发布。似乎至少与扫描相关的所有内容,或者包括外围设备的快速保留和释放都应该在同一个线程中处理。谢谢您的确认!它真的应该在文档中。
-
那么,究竟有什么解决方案呢?有人可以正确回答这个问题吗?将不胜感激。谢谢!
标签: ios iphone bluetooth core-bluetooth