iOS BLE外设后台模式下服务无法恢复问题求助
解决iOS BLE外设应用后台恢复后服务丢失的问题
我看了你的代码和问题描述,核心问题出在后台恢复时的服务处理逻辑上,结合苹果CoreBluetooth的后台机制,我整理了几个关键的修复点:
1. 移除willRestoreState中错误的服务添加逻辑
系统在后台恢复时已经自动帮你重新加载了CBPeripheralManagerRestoredStateServicesKey指定的服务,不需要再次调用add(service)。重复添加服务会导致系统服务注册混乱,反而让连接后的设备无法识别到服务。
你的willRestoreState方法里,self.peripheralManager = peripheral这个赋值也是多余的——代理方法传入的peripheral就是当前的外设管理器实例,重新赋值可能导致引用错乱。
2. 避免蓝牙状态更新时重复创建服务
在peripheralManagerDidUpdateState中,你每次检测到蓝牙poweredOn就调用createServices,但后台恢复后系统已经帮你恢复了服务,重复创建会覆盖掉恢复的服务。需要先判断当前是否已有服务,再决定是否创建。
3. 保存服务的全局引用
把三个核心服务声明为全局变量,这样后台恢复时可以直接关联到系统恢复的服务实例,避免重新创建带来的冲突。
修改后的关键代码片段
首先在AppDelegate顶部添加全局服务变量:
import UIKit import CoreBluetooth @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, CBPeripheralManagerDelegate { var window: UIWindow? var peripheralManager: CBPeripheralManager! var deviceName = "DIGITALBLEND" // 新增全局服务引用 var primaryService: CBMutableService? var nusService: CBMutableService? var dfuService: CBMutableService? // ... 其余代码不变 }
修改createServices方法,添加重复创建校验:
func createServices() { // 检查是否已有服务,避免重复创建 guard peripheralManager.services == nil || peripheralManager.services!.isEmpty else { print("Services already exist, skip re-creation") // 如果广告未开启,重新启动广播 if !peripheralManager.isAdvertising { startAdvertising() } return } //Primary Service let primaryServiceUUID = CBUUID(string: "1ABB0000-542A-3BA1-C243-6F5AAF168DB7") primaryService = CBMutableService(type: primaryServiceUUID, primary: true) //Nordic UARD Service let nusUUID = CBUUID(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E") nusService = CBMutableService(type: nusUUID, primary: true) //Secure DFU Service let dfuUUID = CBUUID(string: "0xFE59") dfuService = CBMutableService(type: dfuUUID, primary: true) //Create characteristics createCharacteristic_PRIMARY(service: primaryService!) createCharacteristic_NUS(service: nusService!) createCharacteristic_DFU(service: dfuService!) }
修改willRestoreState方法,只保存恢复的服务引用并重启广播:
func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) { // 关联系统恢复的服务实例 if let restoredServices = dict[CBPeripheralManagerRestoredStateServicesKey] as? [CBMutableService] { for service in restoredServices { switch service.uuid { case CBUUID(string: "1ABB0000-542A-3BA1-C243-6F5AAF168DB7"): primaryService = service case CBUUID(string: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"): nusService = service case CBUUID(string: "0xFE59"): dfuService = service default: break } } } // 恢复后台广播 if !peripheral.isAdvertising { startAdvertising() } }
额外排查点
- 确认后台权限配置:检查
Info.plist中的UIBackgroundModes是否包含bluetooth-peripheral,没有的话需要添加。 - iOS版本要求:服务恢复功能仅在iOS 11.2及以上版本支持,确保测试设备系统版本符合要求。
- 日志排查:查看Xcode控制台输出,确认
didAdd service和willRestoreState的执行情况,是否有错误信息。
内容的提问来源于stack exchange,提问作者Silvering
相关产品推荐
相关产品推荐

