iOS 中的 CBCentralManager — 它是什么,BLE 管理和 Core Bluetooth

作者: IT Sectr 发布日期: 2026-07-16 阅读时间: 11 分钟

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 — 用于在 Central 角色中管理 BLE 扫描、连接和数据传输的 iOS 类。
  • 扫描通过 scanForPeripherals 启动,并根据服务 UUID 进行过滤以节省能源。
  • 连接通过 connect(peripheral:options:) 进行,并通过委托跟踪状态。
  • iOS 在 BLE 5.0 设备上支持多达 7 个同时 BLE 连接
  • 后台扫描需要在 Background Modes 中启用 bluetooth-central 并使用 CBCentralManagerScanOptionAllowDuplicatesKey。

什么是 CBCentralManager?

CBCentralManager — 是 Core Bluetooth 在 iOS 上实现 Central 角色的主要类。它管理 BLE 连接的整个生命周期:从扫描正在广播的设备到数据传输和断开连接。CBCentralManager 通过 CBCentralManagerDelegate 委托异步工作,通知应用程序蓝牙堆栈中的事件。

CBCentralManager 的初始化启动 state restoration 过程:管理器检查设备上的蓝牙状态,如果应用程序已关闭则恢复以前的连接。初始化过程可能需要 50 到 500 毫秒,具体取决于蓝牙状态。应用程序必须在开始任何 BLE 操作之前等待 centralManagerDidUpdateState 的调用。

Core Bluetooth 架构基于 Delegation 模式:CBCentralManager 将事件处理(设备发现、连接、错误)委托给 CBCentralManagerDelegate 协议。与特定 Peripheral 一起使用 CBPeripheralDelegate 协议,该协议通知服务、特征的发现和数据的接收。这种异步模型确保了 UI 的非阻塞操作。

CBCentralManager 的状态

CBCentralManager 经历多种状态,这些状态决定 BLE 堆栈是否可用于工作。状态通过委托传递:centralManagerDidUpdateState(_:)。开发者必须处理所有状态——不仅仅是 poweredOn,还有蓝牙关闭或不可用的情况。

状态含义开发者的操作
.poweredOn蓝牙已打开并准备就绪开始扫描
.poweredOff蓝牙已关闭向用户显示警告
.unauthorized没有权限在设置中请求权限
.unsupported设备不支持 BLE隐藏 BLE 功能
.unknown状态未定义等待下一次更新
.resetting蓝牙正在重启等待恢复

Unauthorized state 从 iOS 13+ 开始变得越来越常见。从该版本开始,应用程序必须在 Info.plist 中具有 NSBluetoothAlwaysUsageDescription 权限。如果没有它,中央管理器将进入 .unauthorized 状态,扫描将无法进行。用户可以随时在设置 > 隐私 > 蓝牙中更改权限。

扫描 BLE 设备

scanForPeripherals(withServices:options:) — 启动扫描的主要方法。withServices 参数接收服务 UUID 数组以进行过滤:如果传递 nil,将发现所有设备,这会显著增加能耗。建议始终根据应用程序所需服务的 UUID 进行过滤。扫描选项包括 CBCentralManagerScanOptionAllowDuplicatesKey(关于同一设备的重复通知)。

swift
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 为单位的信号强度,在发现时可用。

连接到 Peripheral

connect(_:options:) — 与发现的 Peripheral 建立 BLE 连接的方法。调用 connect 后,iOS 尝试连接到设备。成功连接由 centralManager(_:didConnect:) 确认,错误由 centralManager(_:didFailToConnect:error:) 确认。连接选项包括用于后台通知的 CBConnectPeripheralOptionNotifyOnConnectionKey、CBConnectPeripheralOptionNotifyOnDisconnectionKey 和 CBConnectPeripheralOptionNotifyOnNotificationKey。

swift
// 连接到 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 限制

后台扫描 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 秒。

swift
// 处理断开连接并自动重新连接
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 接收数据。为诊断生产环境中的连接问题,维护错误日志。

常见问题

为什么 CBCentralManager 没有发现设备?

通过 centralManagerDidUpdateState 检查管理器的状态。确保 Info.plist 中存在 NSBluetoothAlwaysUsageDescription 权限,设备上蓝牙已打开,并且外围设备使用正确的类型广播(可连接广播,而非不可连接广播)。

多少个 BLE 设备可以同时连接到 iOS?

在 BLE 5.0 设备上(iPhone 8 及更新版本)— 多达 7 个同时连接。在较旧的设备上 — 多达 3-5 个。扫描的设备数量不受限制,但活动连接有蓝牙控制器设置的严格限制。

在 iOS 上可以多久扫描一次 BLE 而不会消耗电池?

建议使用 UUID 过滤扫描,并在找到设备后关闭扫描。持续扫描会消耗电池:1 小时连续扫描消耗 iPhone 约 10-15% 的电量。使用计时器和条件来停止扫描。

CBCentralManager 和 CBPeripheralManager 之间有什么区别?

CBCentralManager — 用于扫描和连接到外部 BLE 设备(Central 角色)。CBPeripheralManager — 用于让你的 iOS 设备本身充当 BLE 外设(广播服务)。一个实例只能在一个角色中。

如何处理与 BLE 设备的连接丢失?

实现 centralManager(_:didDisconnectPeripheral:error:)。如果错误不为 nil — 使用 exponential backoff 安排自动重新连接(1 秒 → 2 → 4 → 8 → 最大 60)。如果错误为 nil — 设备正常断开(例如,用户按下了设备上的按钮)。

总结

  • CBCentralManager — 用于在 iOS 上的 Central 角色中管理 BLE 扫描、连接和数据传输的 Core Bluetooth 主要类。
  • 扫描通过 scanForPeripherals 启动,可选择按服务 UUID 过滤以减少能耗。
  • 连接通过 connect 进行,成功由 didConnect 确认,错误由 didFailToConnect 在 30 秒超时后确认。
  • 连接后,需要通过 discoverServices 和 discoverCharacteristics 发现服务和特征
  • 后台扫描需要 bluetooth-central Background Mode,并有条件地支持(UUID 过滤,可能的延迟)。
  • iOS 在 BLE 5.0 设备上支持多达 7 个同时 BLE 连接,state restoration 用于重启后恢复。
  • 错误处理和自动重新连接与 exponential backoff — 在 iOS 上构建可靠 BLE 应用的基础。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读