首页 > 解决方案 > 外围设备需要特殊 ACK 时的 CoreBluetooth 和状态保存和恢复

问题描述

我正在使用一个蓝牙外围设备,在连接到它之后会有一个来回的 ACK,然后它才能真正向我发送我需要的数据。

流程是这样的:

  1. 发现外围设备
  2. 连接到外围设备
  3. 发现服务和特征
  4. 监听特定特征的更新
  5. 外设向此特征发送特殊消息
  6. 然后应用程序向外围设备发送 ACK
  7. 外围设备向我发送应用程序所需的数据

我已经在状态保存和恢复的协议方法中实现了所需的逻辑centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any])

问题一:

当应用程序在后台并且 iOS 决定接管蓝牙通信时(出于资源原因),iOS 将如何管理步骤 5、6 和 7?

因为如果不能,那么外围设备将无法发送应用程序在步骤 7 中需要的数据。

问题2:

在文档中,我读到 iOS 可能会在几秒钟内启动您的应用程序。viewDidLoad在那种情况下会执行我的根 ViewController的方法吗?那就是我实例化的地方CBCentralManager


我发现的许多在线资源中的一些:

iOS 应用的核心蓝牙后台处理

iOS 上从零到 BLE——第三部分

标签: iosswiftcore-bluetoothstate-restoration

解决方案


Paulw11 的这两条评论帮助我理解了发生了什么:

不,这不会发生。如果你有一个未决的发现、一个未决的“连接”或者你有一个关于特性的活动通知,那么 iOS 将重新启动你的应用程序,以便它可以处理发现、连接或通知。iOS 无法代表您执行此操作;它不知道你想做什么。– Paulw11


如果您想在后台执行操作,将蓝牙对象附加到视图控制器是个坏主意。我建议你的应用程序委托拥有一个单例或一个对象 - Paulw11


首先,我错误地假设当我的应用程序在后台并且 iOS 不得不终止它时,iOS 将尝试代表我的应用程序处理所有蓝牙通信。现实情况是,iOS 在有限的时间内以后台模式启动应用程序,以便您可以运行恢复代码。

最后,viewDidLoad我的 ViewController 中的逻辑是错误的。我创建了一个BluetoothManager类,并在我的application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool方法中实例化了它AppDelegate


推荐阅读