自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 问题的回复说明:
对于那些没有正确引用CB对象的应用来说,iOS 11通常不会那么宽容......
听起来不是很令人鼓舞。我尝试使用XCode和它的配套工具来分析应用程序并寻找潜在的泄漏,但这并没有给它带来太多启发。
还有其他人遇到类似的问题吗?关于如何解决它的任何建议?关于下一步挖掘的想法?
答案 0 :(得分:1)
经过一段时间的测试后,在我们特定的情况下,解决方案包括将所有与蓝牙堆栈相关的工作转换为 mainQueue 。这意味着所有相关的回调都存在于主线程区域内。
此解决方案在这些回调中执行的工作需要特别谨慎(UI也在此处运行),但是由于大多数 CoreBluetooth 操作默认情况下都是异步的,因此已证明这是可行的。此解决方法已在iOS 11中得到确认,到目前为止,在iOS 12中也未报告任何问题。
这里的重点是:处理 ONLY 中的 mainQueue 中绝对必要的位,然后在必要时将其余负载转移到其他地方。