iOS Swift中PicoX 1设备CoreBluetooth频繁断开问题求助
问题概述
使用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

