CBCentralManager — 是 iOS 中 Core Bluetooth 框架的核心类,它管理 BLE 外围设备的扫描、连接和交互。Core Bluetooth(iOS 5+,2011)在 GATT 级别提供了 BLE 堆栈之上的高级抽象,对开发者隐藏了 Link Layer 和 HCI 的细节。CBCentralManager 扮演 Central 角色:它通过 scanForPeripherals 扫描空域,通过 connect 发起连接,通过 discoverServices 发现服务,并管理数据传输。根据 Apple Developer Documentation(2024),CBCentralManager 在 BLE 5.0 设备上支持多达 7 个同时 BLE 连接。
要点
CBCentralManager — 是 Core Bluetooth 在 iOS 上实现 Central 角色的主要类。它管理 BLE 连接的整个生命周期:从扫描正在广播的设备到数据传输和断开连接。CBCentralManager 通过 CBCentralManagerDelegate 委托异步工作,通知应用程序蓝牙堆栈中的事件。
CBCentralManager 的初始化启动 state restoration 过程:管理器检查设备上的蓝牙状态,如果应用程序已关闭则恢复以前的连接。初始化过程可能需要 50 到 500 毫秒,具体取决于蓝牙状态。应用程序必须在开始任何 BLE 操作之前等待 centralManagerDidUpdateState 的调用。
Core Bluetooth 架构基于 Delegation 模式:CBCentralManager 将事件处理(设备发现、连接、错误)委托给 CBCentralManagerDelegate 协议。与特定 Peripheral 一起使用 CBPeripheralDelegate 协议,该协议通知服务、特征的发现和数据的接收。这种异步模型确保了 UI 的非阻塞操作。
CBCentralManager 经历多种状态,这些状态决定 BLE 堆栈是否可用于工作。状态通过委托传递:centralManagerDidUpdateState(_:)。开发者必须处理所有状态——不仅仅是 poweredOn,还有蓝牙关闭或不可用的情况。
| 状态 | 含义 | 开发者的操作 |
|---|---|---|
| .poweredOn | 蓝牙已打开并准备就绪 | 开始扫描 |
| .poweredOff | 蓝牙已关闭 | 向用户显示警告 |
| .unauthorized | 没有权限 | 在设置中请求权限 |
| .unsupported | 设备不支持 BLE | 隐藏 BLE 功能 |
| .unknown | 状态未定义 | 等待下一次更新 |
| .resetting | 蓝牙正在重启 | 等待恢复 |
Unauthorized state 从 iOS 13+ 开始变得越来越常见。从该版本开始,应用程序必须在 Info.plist 中具有 NSBluetoothAlwaysUsageDescription 权限。如果没有它,中央管理器将进入 .unauthorized 状态,扫描将无法进行。用户可以随时在设置 > 隐私 > 蓝牙中更改权限。
scanForPeripherals(withServices:options:) — 启动扫描的主要方法。withServices 参数接收服务 UUID 数组以进行过滤:如果传递 nil,将发现所有设备,这会显著增加能耗。建议始终根据应用程序所需服务的 UUID 进行过滤。扫描选项包括 CBCentralManagerScanOptionAllowDuplicatesKey(关于同一设备的重复通知)。
import CoreBluetooth
class BLEController: NSObject,
CBCentralManagerDelegate {
private var centralManager: CBCentralManager!
override init() {
super.init()
centralManager =
CBCentralManager(
delegate: self,
queue: nil
)
}
func startScanning() {
let serviceUUID =
CBUUID("180F") // 电池服务
centralManager.scanForPeripherals(
withServices: [serviceUUID],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
}
当发现设备时,会调用 centralManager(_:didDiscover:advertisementData:rssi:)。advertisementData 参数包含广播包数据的完整字典,包括设备名称(CBAdvertisementDataLocalNameKey)、服务 UUID(CBAdvertisementDataServiceUUIDsKey)和制造商数据(CBAdvertisementDataManufacturerDataKey)。RSSI — 以 dBm 为单位的信号强度,在发现时可用。
connect(_:options:) — 与发现的 Peripheral 建立 BLE 连接的方法。调用 connect 后,iOS 尝试连接到设备。成功连接由 centralManager(_:didConnect:) 确认,错误由 centralManager(_:didFailToConnect:error:) 确认。连接选项包括用于后台通知的 CBConnectPeripheralOptionNotifyOnConnectionKey、CBConnectPeripheralOptionNotifyOnDisconnectionKey 和 CBConnectPeripheralOptionNotifyOnNotificationKey。
// 连接到 BLE 设备
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// 为 Peripheral 设置委托
peripheral.delegate = self
}
// 委托:连接成功
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
print("已连接到 " +
"\(peripheral.name ?? "unknown")")
// 开始服务发现
peripheral.discoverServices(nil)
}
// 委托:连接错误
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
print("Connection failed:
\(error?.localizedDescription ?? "")")
}
连接超时在 iOS 上为 30 秒。如果设备在此期间未响应连接请求,将调用 didFailToConnect。影响超时的因素:到设备的距离、干扰、设备当前是否正在广播。在连接之前,确保设备处于可连接广播模式(ADV_IND,而不是 ADV_NONCONN_IND)。
连接后需要发现 Peripheral 的服务(discoverServices)和特征(discoverCharacteristics)。这是读取或写入数据之前的必要步骤。该过程是异步的:discoverServices 通过 peripheral(_:didDiscoverServices:) 返回结果,discoverCharacteristics 通过 peripheral(_:didDiscoverCharacteristicsFor:error:) 返回结果。
建议向 discoverServices 传递感兴趣的 UUID 数组,而不是 nil。过滤可加速发现并节省能源。如果未找到服务,iOS 将报告一个空数组。发现特征后,可以读取它们的值(readValue)、订阅通知(setNotifyValue)或写入数据(writeValue)。
一个重要细节:MTU 在连接后自动协商。要获取当前 MTU,使用 peripheral.maximumWriteValueLength(for: .withResponse) 或 .withoutResponse。在 iOS 中,对于 BLE 5.0 设备,最大 MTU 为 512 字节。如果需要传输大于 MTU 的数据,请在应用程序级别实现分片。
后台扫描 iOS 上的 BLE 设备需要特殊配置。Core Bluetooth 支持后台执行,但有显著的限制。要在后台工作,需要:在项目 Capabilities 的 Background Modes 中启用 bluetooth-central,使用 CBCentralManagerOptionRestoreIdentifierKey 选项初始化 CBCentralManager 以实现状态恢复,并在进入后台时处理中央管理器的事件。
iOS 中后台 BLE 的限制:scanForPeripherals 没有 UUID 过滤在后台不工作。应用程序必须指定用于扫描的特定服务 UUID。iOS 可能会无限期延迟 BLE 事件的传递。Core Bluetooth 在发现匹配设备时自动恢复扫描,即使应用程序在后台。后台扫描超时:iOS 可能在 10-30 分钟后停止扫描以节省能源。
State Restoration — Core Bluetooth 的机制,允许在应用程序重启或 iOS 重启后恢复 BLE 连接。使用方法:在初始化时指定 CBCentralManagerOptionRestoreIdentifierKey,在委托中实现 centralManager(_:willRestoreState:),并从传递的字典中恢复已连接的 Peripheral 列表。State Restoration 对于在后台运行的 BLE 应用程序至关重要,例如健身追踪器或医疗设备。
CBCentralManager 生成错误在几种情况下:连接失败(didFailToConnect)、连接中断(didDisconnectPeripheral)、特征不可读/写(didWriteValue error)。所有 Core Bluetooth 错误都通过带有 CBErrorDomain 域的 Error 对象返回。最常见的代码:CBErrorConnectionTimeout(0x04)、CBErrorPeripheralDisconnected(0x07)、CBErrorOperationNotSupported(0x0A)。
连接恢复策略:在收到 didDisconnectPeripheral 时检查错误代码。如果错误是 CBErrorConnectionTimeout 或 CBErrorPeripheralDisconnected — 在 1-5 秒后安排自动重新连接。如果错误是 CBErrorOperationNotSupported — 记录日志并且不要尝试重复操作。对于关键连接(医疗设备)使用 exponential backoff,最大间隔 60 秒。
// 处理断开连接并自动重新连接
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
guard let error = error else {
return // 预期的断开
}
print("Disconnected: \(error.localizedDescription)")
// 自动重新连接
if shouldAutoReconnect {
DispatchQueue.main.asyncAfter(
deadline: .now() + reconnectDelay
) {
central.connect(peripheral)
}
}
}
在 iOS 上开发可靠的 BLE 应用时考虑:Core Bluetooth 不保证在弱信号时所有数据包的传输。为了可靠传输,使用 writeType .withResponse(确认写入)并订阅通知(setNotifyValue)以从 Peripheral 接收数据。为诊断生产环境中的连接问题,维护错误日志。
常见问题
通过 centralManagerDidUpdateState 检查管理器的状态。确保 Info.plist 中存在 NSBluetoothAlwaysUsageDescription 权限,设备上蓝牙已打开,并且外围设备使用正确的类型广播(可连接广播,而非不可连接广播)。
在 BLE 5.0 设备上(iPhone 8 及更新版本)— 多达 7 个同时连接。在较旧的设备上 — 多达 3-5 个。扫描的设备数量不受限制,但活动连接有蓝牙控制器设置的严格限制。
建议使用 UUID 过滤扫描,并在找到设备后关闭扫描。持续扫描会消耗电池:1 小时连续扫描消耗 iPhone 约 10-15% 的电量。使用计时器和条件来停止扫描。
CBCentralManager — 用于扫描和连接到外部 BLE 设备(Central 角色)。CBPeripheralManager — 用于让你的 iOS 设备本身充当 BLE 外设(广播服务)。一个实例只能在一个角色中。
实现 centralManager(_:didDisconnectPeripheral:error:)。如果错误不为 nil — 使用 exponential backoff 安排自动重新连接(1 秒 → 2 → 4 → 8 → 最大 60)。如果错误为 nil — 设备正常断开(例如,用户按下了设备上的按钮)。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。