[英]iOS 11 CoreBluetooth: Cannot remove an observer CBPeripheral for the key path “delegate”
Ever since iOS 11 was released, I'm experiencing an esporadic but frequent crash with the following signature: 自从iOS 11发布以来,我遇到了一个过度但经常崩溃的问题,其中包括以下签名:
Cannot remove an observer <CBPeripheral 0x1c010ef10> for the key path "delegate" from <CBPeripheral 0x1c010ef10> because it is not registered as an observer.
This happens in the context of a scan for Bluetooth devices, a later connection to one of them and a final cleanup of the whole process. 这种情况发生在蓝牙设备的扫描环境中,后来与其中一个设备的连接以及整个过程的最终清理。 All these tasks are performed in a non-main dispatch queue to soften the pressure on the main thread (for smoother UI experience).
所有这些任务都在非主调度队列中执行,以缓解主线程上的压力(以获得更流畅的UI体验)。 This very code has been running without incident ever since iOS 9 days and only now that iOS 11 came out, started to crash.
自从iOS 9天以来,这个代码一直在运行,并且只是现在iOS 11出现了,开始崩溃。
The only references I've found in the net so far regarding this behaviour are this and this post for the Estimote SDK . 到目前为止,我在网络中找到的关于此行为的唯一参考是这个以及Estimote SDK的 这篇文章。 These references suggest that something might be going on with parallel instances of the CBCentralManager in different dispatch queues, however, nothing regarding special care on the matter is stated in the official Programming Guide .
这些引用表明在不同的调度队列中可能会出现CBCentralManager的并行实例,但是,官方编程指南中没有说明有关此事的特殊注意事项。 Also, a response from an Apple Staff member to another CoreBluetooth issue stating:
此外, Apple工作人员对另一个 CoreBluetooth问题的回复说明:
iOS 11 is in general going to be less forgiving for apps which don't hold a proper reference to CB objects...
对于没有对CB对象进行适当引用的应用程序,iOS 11通常会不那么宽容......
Doesn't sound very encouraging. 听起来不是很鼓舞人心。 I tried profiling the app and looking for potential leaks using XCode and it's companion tools but this didnt't shed much light on it either.
我尝试使用XCode和它的配套工具来分析应用程序并寻找潜在的泄漏,但这也没有给它带来太多启发。
Has anybody else experienced similar issues? 有没有其他人遇到过类似的问题? Any suggestions on how to workaround it?
关于如何解决它的任何建议? Ideas on where to dig next?
关于下一步挖掘的想法?
After some testing period, in our particular case the solution consisted in translating all the Bluetooth stack related work to the mainQueue . 在一段测试期之后,在我们的特定情况下,解决方案包括将所有与蓝牙堆栈相关的工作转换为mainQueue 。 Meaning that all the related callbacks exists within Main-thread territory.
这意味着所有相关的回调都存在于主线程区域内。
This solution requires extra caution with the work performed in those callbacks (UI runs here too), but since most CoreBluetooth actions are asynchronous by default, this has proven feasible. 这个解决方案在这些回调中执行的工作需要格外小心(UI也在这里运行),但由于大多数CoreBluetooth操作默认是异步的,所以这已证明是可行的。 This workaround has been confirmed in iOS 11 and so far no issues have been reported in iOS 12 as well.
此解决方法已在iOS 11中得到确认,到目前为止,iOS 12中也未报告任何问题。
The takeaway here is: Handle ONLY the absolutely necessary bits in mainQueue , and then transfer the rest of the load elsewhere if necessary. 这里要说的是: 只处理mainQueue中绝对必要的位,然后在必要时将其余的负载转移到其他位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.