You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()
    }
}

额外排查点

  1. 确认后台权限配置:检查Info.plist中的UIBackgroundModes是否包含bluetooth-peripheral,没有的话需要添加。
  2. iOS版本要求:服务恢复功能仅在iOS 11.2及以上版本支持,确保测试设备系统版本符合要求。
  3. 日志排查:查看Xcode控制台输出,确认didAdd service和willRestoreState的执行情况,是否有错误信息。

内容的提问来源于stack exchange,提问作者Silvering

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 13:57:30