iOS 11 CoreBluetooth:无法删除密钥路径的外围设备;“代表”;

iOS 11 CoreBluetooth:无法删除密钥路径的外围设备;“代表”;,ios,iphone,bluetooth,core-bluetooth,Ios,Iphone,Bluetooth,Core Bluetooth,自从iOS 11发布以来,我就经历了一次esporadic但频繁的崩溃,其特征如下: Cannot remove an observer <CBPeripheral 0x1c010ef10> for the key path "delegate" from <CBPeripheral 0x1c010ef10> because it is not registered as an observer. 无法从中删除密钥路径“委托”的观察者,因为它未注册为观察者。 这是在扫

自从iOS 11发布以来,我就经历了一次esporadic但频繁的崩溃,其特征如下:

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的和post。这些参考资料表明,在不同的调度队列中,CBCentralManager的并行实例可能正在发生一些事情,但是,官方文件中没有说明对此事的特别注意。此外,苹果员工核心蓝牙问题的回复指出:

iOS 11通常不会原谅那些没有正确引用CB对象的应用程序

听起来不太令人鼓舞。我试着用XCode及其配套工具分析应用程序并寻找潜在的漏洞,但这也没有给它带来太多的启示


还有其他人经历过类似的问题吗?对如何解决这个问题有什么建议吗?关于下一步在哪里挖掘的想法?

经过一段时间的测试后,在我们的特定案例中,解决方案包括将所有与蓝牙协议栈相关的工作转换到主队列。这意味着所有相关回调都存在于主线程区域内

此解决方案需要特别注意在这些回调中执行的工作(UI也在此处运行),但由于大多数CoreBluetooth操作在默认情况下是异步的,这已被证明是可行的。iOS 11中已经确认了此解决方案,到目前为止,iOS 12中也没有报告任何问题


这里的要点是:仅处理主队列中绝对必要的位,然后在必要时将其余的负载转移到其他位置。

自iOS 11以来,我经历了同样的事情,我同样不确定原因或如何解决它。在与一名苹果员工的私人交流中,他建议在同一个线程中处理所有CBCentral活动,因为回调和其他消息事件都会向对象发送信号。显然,如果结果对象(如cbperipal)在其他线程中被处理和释放,则所提到的信令可能会引用已释放的对象,从而导致崩溃。虽然还没有明确的结论,但经过反复试验,我个人也得出了相同的结论,但在我确认这一点之前,我不想写在这里。这一知识应该以更易于搜索的方式发布。看来至少所有与扫描相关的事情,或者包括快速保留和释放外设都应该在同一个线程中处理。谢谢你的确认!它真的应该在文档中。那么,这到底是什么解决方案呢?有人能正确回答这个问题吗?我们将不胜感激。谢谢