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

iOS Swift中PicoX 1设备CoreBluetooth频繁断开问题求助

iOS CoreBluetooth连接PicoX 1反复断开问题解决方案

问题概述

使用Swift的CoreBluetooth框架连接PicoX 1设备时,可成功建立连接,但每隔5-6秒自动断开,报错:Error Domain=CBErrorDomain Code=0 "Unknown error." UserInfo={NSLocalizedDescription=Unknown error.}

核心问题排查与修复

1. 移除重复的服务发现调用

在didConnect方法中连续调用两次discoverServices,会导致蓝牙栈重复执行服务发现操作,干扰连接稳定性。

修改前代码:

func centralManager(_ central: CBCentralManager,  didConnect peripheral: CBPeripheral){
    print("Connected to "+peripheral.name!)
    peripheral.delegate = self
    peripheral.discoverServices(nil)
   
    print("Connected to your Particle Board")
    peripheral.discoverServices([ParticlePeripheral.testUUID])
 
}

修改后代码:

func centralManager(_ central: CBCentralManager,  didConnect peripheral: CBPeripheral){
    print("Connected to "+peripheral.name!)
    peripheral.delegate = self
    // 仅调用一次,指定目标服务UUID,避免无意义的全量扫描
    peripheral.discoverServices([ParticlePeripheral.testUUID])
    print("Connected to your Particle Board")
}

2. 持有CBPeripheral的强引用

若未在类中保留CBPeripheral的强引用,系统可能在连接后释放该对象,导致连接意外断开。

添加类属性:

class YourViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
    private var centralManager: CBCentralManager!
    // 新增强引用属性,保留连接的外设
    private var connectedPeripheral: CBPeripheral?
    
    // ... 其他代码
}

在连接时赋值:

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral){
    print("Connected to "+peripheral.name!)
    self.connectedPeripheral = peripheral
    peripheral.delegate = self
    peripheral.discoverServices([ParticlePeripheral.testUUID])
    print("Connected to your Particle Board")
}

3. 调整扫描选项

CBCentralManagerScanOptionAllowDuplicatesKey设为true会让系统重复发现同一设备,而你在didDiscover中立刻停止扫描,该设置完全多余,还可能干扰蓝牙连接逻辑。

修改扫描代码:

@IBAction func btnScanClick( sender: Any) {
    print("scan Start")
    // 移除AllowDuplicates选项,或设为false
    centralManager.scanForPeripherals(withServices: [ParticlePeripheral.testUUID], options: nil)
    DispatchQueue.main.asyncAfter(deadline: .now() + 30.0) {
        if self.centralManager.isScanning{
            self.centralManager.stopScan()
            print("Scanning stop")
        }
    }
}

4. 优化连接选项,添加保持连接配置

连接时添加CBConnectPeripheralOptionNotifyOnDisconnectionKey和CBConnectPeripheralOptionRestoreIdentifierKey,帮助系统维持稳定连接:

修改连接代码:

func centralManager( _ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    centralManager.stopScan()
    print("Discovered \(peripheral.name ?? "")")
    // 添加连接选项,提升连接稳定性
    let connectOptions: [String: Any] = [
        CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
        CBConnectPeripheralOptionRestoreIdentifierKey: "PicoX1Connection"
    ]
    self.centralManager.connect(peripheral, options: connectOptions)
}

5. 调整特征值操作顺序,减少不必要的读取

同时调用readValue和setNotifyValue(true)可能给设备造成负载,部分蓝牙设备会因频繁操作断开连接。可先开启通知,按需读取,或移除重复的读取操作:

修改特征发现代码:

func peripheral(_ peripheral: CBPeripheral,didDiscoverCharacteristicsFor service: CBService,error: Error?){
    if let characteristics = service.characteristics {
        for characteristic in characteristics {
            print("characteristic found >> : ",characteristic)
            print("characteristic.properties found >> : ",characteristic.properties)
            
            if characteristic.uuid == ParticlePeripheral.BATTERY_LEVEL_CHAR_UUID {
                print("BATTERY_LEVEL_CHAR_UUID characteristic found")
                // 先开启通知,再按需读取(比如在通知回调中处理)
                peripheral.setNotifyValue(true, for: characteristic)
                // 若不需要立即读取,可移除readValue调用
                // peripheral.readValue(for: characteristic)
            }else if characteristic.uuid == ParticlePeripheral.RX_CHARACTERISTIC_UUID{
                print("RX_CHARACTERISTIC_UUID characteristic found")
                peripheral.setNotifyValue(true, for: characteristic)
            }else if characteristic.uuid == ParticlePeripheral.TX_CHARACTERISTIC_UUID{
                print("TX_CHARACTERISTIC_UUID characteristic found")
                peripheral.setNotifyValue(true, for: characteristic)
            }
        }
    }
    print(error)
}

6. 实现断开回调,获取详细错误信息

当前未实现centralManager(_:didDisconnectPeripheral:error:)方法,无法获取真实的断开原因。添加该方法排查问题:

添加断开回调:

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
    print("Disconnected from \(peripheral.name ?? "unknown device")")
    if let error = error {
        print("Disconnection error: \(error.localizedDescription), code: \((error as NSError).code)")
    }
    // 可根据需求尝试重连
    // central.connect(peripheral, options: connectOptions)
}

额外排查方向

  • 检查PicoX 1设备的蓝牙固件是否为最新版本,部分旧固件存在连接稳定性问题。
  • 确保设备与iOS设备的距离在合理范围内,避免信号干扰导致断开。
  • 关闭iOS设备的蓝牙再重新开启,清除蓝牙缓存后重试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:14:54