应用被系统终止时WillRestoreState未调用的技术求助
嘿,针对你开发iOS血压计APP时遇到的状态恢复需求,我来给你梳理一套完整的实现方案,帮你确保APP被系统终止后,还能被血压计的数据传输唤起:
一、先搞定项目的后台权限配置
这是基础中的基础,没配置好权限一切都是白搭:
- 打开Xcode项目的
Info.plist,添加UIBackgroundModes数组,把bluetooth-central加进去(因为你的APP是作为BLE中心设备连接血压计) - 或者更直观的方式:在项目target的
Signing & Capabilities面板里,添加Background Modes权限,勾选Uses Bluetooth LE accessories选项
二、正确初始化CBCentralManager并配置状态恢复参数
你已经迈出第一步了,这里给你补全正确的配置细节:
- 初始化中心管理器时,必须指定唯一的恢复标识符(
CBCentralManagerOptionRestoreIdentifierKey),这是系统用来识别并恢复你的BLE会话的关键。同时后台队列建议用并发队列(也可以用串行,并发更高效):
let bleDispatchQueue = DispatchQueue(label: "com.xyz.ios.ble", attributes: .concurrent) let initOptions: [String: Any] = [ CBCentralManagerOptionShowPowerAlertKey: true, // 蓝牙关闭时弹出提示 CBCentralManagerOptionRestoreIdentifierKey: "com.xyz.ios.ble.central.restore" // 唯一的恢复标识,别跟其他APP重复 ] let centralManager = CBCentralManager(delegate: self, queue: bleDispatchQueue, options: initOptions)
- 划重点:这个恢复标识符一定要唯一,一个APP里如果有多个CBCentralManager实例,每个都得用不同的标识,否则系统没法正确恢复状态。
三、实现状态恢复的Delegate回调
当系统把你的APP从终止状态唤起时,会自动调用这个方法,你需要在这里恢复之前的BLE连接和扫描状态:
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String: Any]) { // 恢复之前连接的外设 if let restoredPeripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] { for peripheral in restoredPeripherals { peripheral.delegate = self // 重新绑定代理,不然收不到数据回调 central.connect(peripheral, options: nil) // 尝试重新连接 } } // 恢复之前的扫描状态(如果APP终止前在扫描的话) if let scanServices = dict[CBCentralManagerRestoredStateScanServicesKey] as? [CBUUID] { let scanOptions = dict[CBCentralManagerRestoredStateScanOptionsKey] as? [String: Any] central.scanForPeripherals(withServices: scanServices, options: scanOptions) } }
四、确保外设数据能唤起APP
要让血压计的数据传输能唤起终止的APP,关键是订阅外设特征的**通知(Notify)**模式:
- 连接血压计后,先发现它的服务(血压服务的UUID是
0x1810,符合蓝牙医疗设备规范),然后找到血压测量的特征(UUID是0x2A35),订阅它的通知:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard let services = peripheral.services else { return } for service in services { if service.uuid == CBUUID(string: "1810") { // 匹配血压服务 peripheral.discoverCharacteristics(nil, for: service) } } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { if characteristic.uuid == CBUUID(string: "2A35") { // 匹配血压测量特征 peripheral.setNotifyValue(true, for: characteristic) // 开启通知 } } }
这样当血压计有新数据时,会主动发送通知给你的APP,哪怕APP已经被系统终止,系统也会自动把APP唤起到后台处理数据。
五、测试和避坑要点
- 正确测试状态恢复:别直接点Xcode的停止按钮终止APP,这样不会触发系统的状态恢复逻辑。正确步骤是:
- 运行APP,连接血压计并订阅通知
- 按Home键把APP切到后台
- 在多任务界面划掉APP(模拟系统终止)
- 让血压计发送新数据,系统会自动唤起APP到后台,你可以在Xcode控制台看到日志
- 别乱用后台任务:BLE后台模式是iOS专门支持的,不需要额外申请
beginBackgroundTask,系统会自动处理唤起和后台运行时间 - 代理必须及时绑定:恢复外设连接后,一定要重新设置外设的delegate,否则收不到数据回调
内容的提问来源于stack exchange,提问作者user3838337
相关产品推荐
相关产品推荐

