核心流程与代码实现
环境配置

import CoreBluetooth
class BluetoothManager: NSObject, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
var connectedPeripheral: CBPeripheral?
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
scanForDevices()
case .poweredOff:
print("蓝牙未开启")
default: break
}
}
}
设备扫描与过滤
func scanForDevices() {
// 筛选心率监测设备
let heartRateServiceUUID = CBUUID(string: "180D")
centralManager.scanForPeripherals(withServices: [heartRateServiceUUID],
options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi RSSI: NSNumber) {
guard let name = peripheral.name, name.contains("HRM") else { return }
connectedPeripheral = peripheral
centralManager.connect(peripheral, options: nil)
}
设备连接与服务发现
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices(nil) // 发现所有服务
}
// CBPeripheralDelegate
func peripheral(_ peripheral: CBPeripheral,
didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print("发现服务: (service.uuid)")
peripheral.discoverCharacteristics(nil, for: service)
}
}
数据传输处理
func peripheral(_ peripheral: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?) {
guard let characteristics = service.characteristics else { return }
for characteristic in characteristics {
// 订阅心率测量特征
if characteristic.uuid == CBUUID(string: "2A37") {
peripheral.setNotifyValue(true, for: characteristic)
}
// 读取设备信息
if characteristic.uuid == CBUUID(string: "2A29") {
peripheral.readValue(for: characteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
guard let data = characteristic.value else { return }
switch characteristic.uuid {
case CBUUID(string: "2A37"):
let heartRate = parseHeartRate(data)
print("当前心率: (heartRate)bpm")
case CBUUID(string: "2A29"):
let model = String(data: data, encoding: .utf8)
print("设备型号: (model ?? "")")
default: break
}
}
关键问题解决方案
后台运行支持
在Info.plist中添加:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>
连接优化策略

// 断线自动重连
func centralManager(_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?) {
if let peripheral = connectedPeripheral {
centralManager.connect(peripheral, options: nil)
}
}
// 连接超时处理
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
if self.connectedPeripheral?.state != .connected {
self.centralManager.cancelPeripheralConnection(peripheral)
}
}
数据分包处理
// 处理长数据分包
var packetBuffer = Data()
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
guard let data = characteristic.value else { return }
if characteristic.properties.contains(.notify) {
packetBuffer.append(data)
if !characteristic.isNotifying {
processCompletePacket(packetBuffer)
packetBuffer.removeAll()
}
}
}
安全实践建议
-
配对加密
// 请求配对 peripheral.openL2CAPChannel(PSM: 31) // PSM需根据设备协议指定
-
数据验证
func validateChecksum(_ data: Data) -> Bool { var checksum: UInt8 = 0 data.dropLast().forEach { checksum ^= $0 } return checksum == data.last } -
权限管理
// 在Info.plist中配置 <key>NSBluetoothAlwaysUsageDescription</key> <string>需要蓝牙权限连接健康设备</string>
性能优化技巧
-
连接参数协商

let connectionOptions: [String: Any] = [ CBConnectPeripheralOptionNotifyOnConnectionKey: true, CBConnectPeripheralOptionNotifyOnDisconnectionKey: true, CBConnectPeripheralOptionNotifyOnNotificationKey: true ] centralManager.connect(peripheral, options: connectionOptions)
-
动态扫描策略
// 根据电量调整扫描间隔 func adjustScanRate(batteryLevel: Float) { centralManager.stopScan() let interval = batteryLevel > 0.2 ? 5.0 : 30.0 Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in self.centralManager.scanForPeripherals(withServices: nil) } }
实战经验分享
-
设备兼容性处理
// 双模蓝牙适配 #if os(iOS) let manager = CBCentralManager(delegate: self, queue: nil) #elseif os(macOS) let manager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true]) #endif -
错误诊断代码
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error as? CBError { switch error.code { case .writeNotPermitted: print("写入权限被拒绝") case .invalidHandle: print("无效的特征句柄") default: print("未知错误: (error.localizedDescription)") } } }
测试提示:使用Apple的Bluetooth Explorer工具(需下载Apple附加工具)模拟BLE设备进行全流程测试。
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/34596.html
评论列表(3条)
教程挺实用的,但自动重连会不会在某些设备密集的地方导致频繁断连重试,反而拖慢应用响应呢?
这篇文章讲iOS蓝牙断线自动重连的教程真挺实用的!作为错误码收藏家,我平时就爱琢磨各种蓝牙错误码,比如CBCentralManagerStateDisconnected或CBErrorConnectionTimeout这些常见的坑,实际开发中蓝牙断线太频繁了,用户动不动就抱怨连接失败。作者通过CoreBluetooth实战讲解自动重连流程,我觉得核心是把错误监控和重试逻辑结合好,比如一检测到断线就立马后台重连,省得用户手动操作。不过,教程里如果再多提点具体错误码的处理策略就更棒了,毕竟不同错误码对应不同重连方式,能避免无限循环重试的尴尬。整体来说,内容很接地气,开发者们参考起来应该能少走弯路,期待更多类似分享!(约150字)
这篇文章讲蓝牙自动重连真有用!CoreBluetooth的并发设计让我学到不少,多线程处理断开重连的场景很巧妙,赞一个!