SwiftUI开发iOS App通过蓝牙连接Raspberry Pi 4遇连接问题
问题诊断与修复方案
你的代码存在几个关键问题,导致连接后无法触发预期回调,看起来像是“连接失败”,实际是代理方法未被正确调用加上外设引用管理不当:
1. 代理方法签名错误
你写的didConnectPeripheral是旧Objective-C风格的Swift写法,不符合CoreBluetooth最新的代理方法签名,系统根本不会回调这个方法。正确的方法签名应该是:
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { // 连接成功后的逻辑 }
2. 未持有CBPeripheral强引用
在didDiscover里直接调用connect后,没有保存这个CBPeripheral实例的强引用,它可能被ARC释放,导致连接流程中断或后续服务发现失败。需要在BLEManager里添加属性持有已连接外设:
@Published var connectedPeripheral: CBPeripheral?
连接时赋值:
myCentral.connect(peripheral, options: nil) self.connectedPeripheral = peripheral
3. 重复添加外设到数组
didDiscover会多次扫描到同一个外设,你的代码每次都往peripherals数组里添加,导致重复数据。可以通过外设identifier判断是否已存在,避免重复添加:
let isAlreadyAdded = peripherals.contains { $0.id == peripheral.identifier.uuidString } if !isAlreadyAdded { let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue) peripherals.append(newPeripheral) }
(建议把Peripheral的id改成外设uuidString,而非数组count,这样更准确)
完整修改后的代码示例
class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { var myCentral: CBCentralManager! @Published var isSwitchedOn = false @Published var peripherals = [Peripheral]() @Published var connectedPeripheral: CBPeripheral? // 新增:持有已连接外设 override init() { super.init() myCentral = CBCentralManager(delegate: self, queue: nil) } func centralManagerDidUpdateState(_ central: CBCentralManager) { isSwitchedOn = central.state == .poweredOn } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String ?? "Unknown" // 匹配目标外设UUID if peripheral.identifier.uuidString == "6D915395-3E79-0072-22A3-009DDC331F7C" { myCentral.stopScan() myCentral.connect(peripheral, options: [CBConnectPeripheralOptionNotifyOnDisconnectionKey: true]) connectedPeripheral = peripheral // 持有引用 print("开始连接目标外设") } // 避免重复添加外设 let isAlreadyAdded = peripherals.contains { $0.id == peripheral.identifier.uuidString } if !isAlreadyAdded { let newPeripheral = Peripheral(id: peripheral.identifier.uuidString, name: peripheralName, rssi: RSSI.intValue) peripherals.append(newPeripheral) } } // 修正后的连接成功回调方法 func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { peripheral.delegate = self // 发现服务/特征需设置peripheral代理 peripheral.discoverServices(nil) print("连接成功:\(peripheral.name ?? "Unknown")") } // 新增连接失败回调,方便排查问题 func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { print("连接失败:\(error?.localizedDescription ?? "未知错误")") } // 外设服务发现回调(可选,按需实现) func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let error = error { print("发现服务失败:\(error.localizedDescription)") return } peripheral.services?.forEach { service in peripheral.discoverCharacteristics(nil, for: service) } } } // 修改Peripheral的id类型为外设UUID struct Peripheral: Identifiable { let id: String let name: String let rssi: Int }
额外排查点
- 确认树莓派4的BLE服务正常广播,且无连接数量限制
- 检查iOS设备蓝牙权限是否完全开启(设置->隐私与安全性->蓝牙)
- 通过
didFailToConnect回调的错误信息,直接定位连接失败原因
内容的提问来源于stack exchange,提问作者Arda Yasar
相关产品推荐
相关产品推荐

