Core Bluetooth 是 Apple 用于在 iOS、iPadOS 和 macOS 上与 Bluetooth Low Energy 交互的框架。该框架提供了一整套 API,用于在 BLE 的两种角色中工作:中央设备 (CBCentralManager) 用于扫描和连接外围设备,以及外围设备 (CBPeripheralManager) 用于模拟 BLE 服务器。Core Bluetooth 将 BLE 协议栈从物理无线电抽象到应用 GATT 配置文件。根据 Apple Developer,2026,Core Bluetooth 是 Apple 唯一官方的 BLE 开发 API,支持 BLE 4.0–5.4,具有 extended advertising、2M PHY 和 LE Audio。
要点
Core Bluetooth 将 BLE 协议栈分为由 Bluetooth SIG 规范定义的两个逻辑角色。中央设备角色 (Central) 由 CBCentralManager 类表示 — 它启动扫描、建立连接并管理已连接 CBPeripheral 的列表。外围设备角色 (Peripheral) 由 CBPeripheralManager 表示 — 它发布服务和特性、响应中央的请求并发送通知。一个 iOS 会话可以同时在多个 BLE 无线电上以两种角色工作,但典型应用使用一种角色。
Core Bluetooth 架构包括五个关键抽象。 CBCentralManager 管理设备蓝牙适配器的状态:poweredOn(准备就绪)、poweredOff(蓝牙已关闭)、unauthorized(无权限)、unsupported(BLE 不可用)。 CBPeripheral 表示一个远程 BLE 设备及其 UUID、名称、RSSI 和 GATT 层次结构。 CBService — 特性的逻辑组。 CBCharacteristic — 用于读取/写入/通知的数据点。 CBPeripheralManager 创建本地 GATT 服务器以模拟外围设备。
| 类 | 角色 | 主要方法 |
|---|---|---|
| CBCentralManager | 中央设备 | scanForPeripherals, connect, cancelPeripheralConnection, retrievePeripherals |
| CBPeripheral | 远程外围设备 | discoverServices, discoverCharacteristics, readValue, writeValue, setNotifyValue |
| CBPeripheralManager | 本地外围设备 | addService, removeService, startAdvertising, respondToRequest, updateValue |
| CBCentral | 远程中央 | maximumUpdateValueLength, identifier, ancsAuthorized |
CBCentralManager 状态管理所有 BLE 操作。应用启动时,使用当前蓝牙状态调用 centralManagerDidUpdateState。如果状态不是 .poweredOn,系统将忽略任何 BLE 调用。开发人员必须在每次扫描和连接之前检查状态。从 .poweredOff 到 .poweredOn 的转换在 iOS 设置中打开蓝牙时发生 — 委托收到重复调用,应用可以恢复扫描。
CBCentralManager — 从中央设备端进行所有 BLE 操作的入口点。初始化接受一个委托 (CBCentralManagerDelegate) 和一个 DispatchQueue 队列 — Apple 建议使用 main queue 以简化或 serial queue 以提高性能。初始化后,框架自动检查蓝牙状态并调用 centralManagerDidUpdateState: — 第一个需要处理的必需委托。
扫描通过 scanForPeripheralsWithServices:options: 方法启动。第一个参数是用于过滤的 CBUUID 服务数组:如果已知感兴趣服务的 UUID,传递它们可以减少能耗和搜索时间。如果为 nil,则检测范围内的所有 BLE 设备。选项包括 .allowDuplicatesKey(重复检测同一设备)和 .solicitedServiceUUIDsKey(用于在中央上发布的服务)。
import CoreBluetooth
class BLECentral: NSObject {
private var centralManager: CBCentralManager!
private var discoveredPeripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: .main)
}
// 开始 BLE 扫描
func startScan() {
guard centralManager.state == .poweredOn else {
print("蓝牙不可用")
return
}
// 扫描所有设备(nil = 无过滤)
centralManager.scanForPeripherals(withServices: nil,
options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
}
// 停止扫描
func stopScan() {
centralManager.stopScan()
}
// 连接到所选设备
func connect(to peripheral: CBPeripheral) {
centralManager.connect(peripheral, options: nil)
}
}
// MARK: - CBCentralManagerDelegate
extension BLECentral: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
startScan()
}
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi: NSNumber) {
if !discoveredPeripherals.contains(where: { $0.identifier == peripheral.identifier }) {
discoveredPeripherals.append(peripheral)
print("Found devices: \(peripheral.name ?? "Unknown"), RSSI: \(rssi)")
}
}
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
print("Connected: \(peripheral.identifier)")
peripheral.delegate = self
peripheral.discoverServices(nil)
}
func centralManager(_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?) {
print("Disconnected: \(peripheral.identifier)")
}
}
BLECentral 类演示了扫描和连接 BLE 设备的完整周期。当蓝牙打开时,centralManagerDidUpdateState 启动扫描。didDiscoverPeripheral 将找到的设备收集到 discoveredPeripherals 数组中,并根据标识符进行去重。连接后 (didConnect),立即启动服务发现 — 这是任何 GATT 操作之前的必需步骤。
CBPeripheralManager — 用于在 iOS 上模拟 BLE 外围设备的类。处于外围角色中的应用可以发布自己的服务和特性,接收来自中央设备的传入读/写请求,并发送通知。CBPeripheralManager 用于由 iPhone 模拟的 BLE 配件:遥控器、键盘、追踪器、IoT 网关。
CBPeripheralManager 的生命周期从初始化和 CBPeripheralManagerDelegate 委托开始。通过 peripheralManagerDidUpdateState: 确认 poweredOn 后,发布服务 (addService:) 并启动广播 (startAdvertising:)。CBAdvertisementData 广播数据包括本地名称 (CBAdvertisementDataLocalNameKey)、服务 UUID (CBAdvertisementDataServiceUUIDsKey) 和功率级别 (CBAdvertisementDataTxPowerLevelKey)。广播包最大大小为 BLE 4.0 为 31 字节,BLE 5.0+ extended advertising 为 251 字节。
// 通过 CBPeripheralManager 在 iOS 上实现 BLE 外围设备
class BLEPeripheral: NSObject {
private var peripheralManager: CBPeripheralManager!
let serviceUUID = CBUUID(string: "1234")
let characteristicUUID = CBUUID(string: "5678")
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: .main)
}
// 发布带有特性的服务
func setupService() {
let characteristic = CBMutableCharacteristic(
type: characteristicUUID,
properties: [.read, .write, .notify],
value: nil,
permissions: [.readable, .writeable]
)
let service = CBMutableService(type: serviceUUID, primary: true)
service.characteristics = [characteristic]
peripheralManager.add(service)
}
// 开始广播
func startAdvertising() {
let advertisementData: [String: Any] = [
CBAdvertisementDataLocalNameKey: "My BLE Device",
CBAdvertisementDataServiceUUIDsKey: [serviceUUID]
]
peripheralManager.startAdvertising(advertisementData)
}
}
// MARK: - CBPeripheralManagerDelegate
extension BLEPeripheral: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
setupService()
}
}
func peripheralManager(_ peripheral: CBPeripheralManager,
didAdd service: CBService,
error: Error?) {
if error == nil {
startAdvertising()
}
}
// 处理读取请求
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveRead request: CBATTRequest) {
let data = "CurrentValue".data(using: .utf8)!
request.value = data
peripheralManager.respond(to: request, withResult: .success)
}
// 处理写入请求
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveWrite requests: [CBATTRequest]) {
for request in requests {
if let value = request.value {
print("Write: \(value)")
}
}
peripheralManager.respond(to: requests.first!, withResult: .success)
}
}
BLEPeripheral 类创建一个 BLE 服务器,具有一个支持读取、写入和通知的特性。初始化后,peripheralManagerDidUpdateState 通过 addService: 发布服务,然后通过 startAdvertising: 启动广播。didReceiveRead 和 didReceiveWrite 处理程序响应来自中央设备的传入 GATT 请求。发送通知使用 updateValue:forCharacteristic:onSubscribedCentrals: 方法。
GATT 操作(通用属性协议) — Core Bluetooth 中数据交换的基础。发现服务和特性后,中央设备可以执行三种类型的操作:读取特性值、写入值和订阅通知/指示。每个操作都是异步的,并通过相应的 CBPeripheralDelegate 委托返回结果。
读取 通过调用 readValueForCharacteristic: 执行。值在 peripheral:didUpdateValueForCharacteristic:error: 中到达。重要提示:读取返回来自设备的当前值,而不是缓存值。如果设备不支持读取 (.read 属性),调用将返回错误。对于大值(大于 MTU),BLE 在 GATT 级别自动分段和组装数据。
写入 通过 writeValue:forCharacteristic:type: 执行。BLE 支持两种写入模式:withResponse(可靠,带确认)和 withoutResponse(快速,无确认)。CBCharacteristic.properties 属性确定可用的写入类型。单个写入包的最大大小受 MTU 限制:BLE 4.0 为 23 字节(20 字节有效数据 + 3 字节标头),BLE 5.0 具有 extended MTU 为 247 字节(MTU 251)。
通知 通过调用 setNotifyValue:true forCharacteristic: 激活。订阅后,每当特性值更改时,外围设备通过 peripheral:didUpdateValueForCharacteristic: 自动发送更新。要禁用通知,调用 setNotifyValue:false forCharacteristic:。Core Bluetooth 自动管理外围设备上的 CCCD 描述符。
| 操作 | 方法 | 委托 | 传输类型 |
|---|---|---|---|
| 读取 | readValueForCharacteristic: | didUpdateValueForCharacteristic | 轮询(请求-响应) |
| 写入 withResponse | writeValue:forCharacteristic:type:withResponse | didWriteValueForCharacteristic | 带确认 |
| 写入 withoutResponse | writeValue:forCharacteristic:type:withoutResponse | 无委托 | 无确认 |
| 通知 | setNotifyValue:true forCharacteristic: | didUpdateNotificationStateForCharacteristic + didUpdateValueForCharacteristic | 来自外围设备的推送 |
后台模式 Core Bluetooth 允许 BLE 应用在后台继续扫描、保持连接和接收通知。激活需要:在 Xcode 中启用 capability “Uses Bluetooth LE accessories” (Info.plist → Required background modes → App communicates using Core Bluetooth) 并将 „bluetooth-central” 键添加到 UIBackgroundModes。对于外围角色 — „bluetooth-peripheral”。
状态恢复 — Core Bluetooth 的机制,用于在 iOS 系统重启应用后恢复 BLE 连接状态。当激活后台模式并在 CBCentralManager 或 CBPeripheralManager 初始化中指定 restoreIdentifier 时,iOS 在应用终止时保存 BLE 协议栈状态,并在下次启动时恢复。委托 centralManager:willRestoreState: 接收一个包含已保存 CBPeripheral 和待处理连接的字典。
// 具有状态恢复功能的 Core Bluetooth 配置
class BLECentralWithRestoration: NSObject {
let restoreIdentifier = "com.app.blecentral"
private var centralManager: CBCentralManager!
override init() {
super.init()
let options: [String: Any] = [
CBCentralManagerOptionRestoreIdentifierKey: restoreIdentifier,
CBCentralManagerOptionShowPowerAlertKey: true
]
centralManager = CBCentralManager(delegate: self,
queue: nil,
options: options)
}
}
extension BLECentralWithRestoration: CBCentralManagerDelegate {
// 重启后恢复状态
func centralManager(_ central: CBCentralManager,
willRestoreState dict: [String : Any]) {
if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
as? [CBPeripheral] {
for peripheral in peripherals {
peripheral.delegate = self
// 恢复 GATT 发现
peripheral.discoverServices(nil)
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("恢复后蓝牙准备就绪")
}
}
}
在 BLECentralWithRestoration 配置中,CBCentralManagerOptionRestoreIdentifierKey 键激活状态保存。如果应用被 iOS 终止(例如由于内存不足),下次启动时 centralManager:willRestoreState: 接收先前连接的 CBPeripheral 列表。应用恢复委托并重新发现服务 — 用户不会注意到连接中断。没有状态恢复,所有 BLE 会话在应用终止时丢失。
完整示例 Swift 中的 BLE 应用将中央和外围设备结合在一个项目中。应用可以在两种模式下工作:检测并连接 BLE 设备(中央)或模拟 BLE 配件(外围)。下面呈现了具有在启动时选择角色的通用 BLE 管理器的架构。
// 用于中央和外围的通用 BLE 管理器
class BLEManager {
enum Role {
case central
case peripheral
}
private let role: Role
private var centralManager: CBCentralManager?
private var peripheralManager: CBPeripheralManager?
let advertisedServiceUUID = CBUUID(string: "A001")
init(role: Role) {
self.role = role
switch role {
case .central:
centralManager = CBCentralManager(delegate: nil, queue: .main)
case .peripheral:
peripheralManager = CBPeripheralManager(delegate: nil, queue: .main)
}
}
// 中央设备:扫描
func scanForDevices() {
centralManager?.scanForPeripherals(withServices: nil, options: nil)
}
// 外围设备:广播
func advertiseService() {
let data: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [advertisedServiceUUID]
]
peripheralManager?.startAdvertising(data)
}
}
// 启动时使用
let isCentral = UserDefaults.standard.bool(forKey: "isCentral")
let manager = BLEManager(role: isCentral ? .central : .peripheral)
if isCentral {
manager.scanForDevices()
} else {
manager.advertiseService()
}
BLEManager 管理器在初始化时选择角色并创建相应的 Manager(CBCentralManager 或 CBPeripheralManager)。角色标志可以存储在 UserDefaults 中或通过配置服务器传递。这种方法允许 BLE 应用适应使用场景:在销售点,iPhone 作为中央扫描支付终端,在 IoT 网关上 — 作为外围从传感器收集数据。
常见问题
Core Bluetooth — Apple 用于在 iOS、iPadOS 和 macOS 上进行 BLE 开发的框架。为中央 (CBCentralManager) 和外围 (CBPeripheralManager) 设备的操作提供 API。支持 BLE 4.0–5.4、extended advertising、2M PHY 和 LE Audio。Core Bluetooth 是 Apple 唯一官方的 BLE 通信 API,对于所有使用 Bluetooth Low Energy 的 iOS 应用都是必需的。
CBCentralManager — 用于在中央设备角色中工作的类:扫描 BLE 外围设备、建立连接、读取和写入特性。 CBPeripheralManager — 用于在外围角色中工作的类:发布服务、响应读/写请求和发送通知。一部 iPhone 可以通过不同的管理器实例同时在两个角色中工作。
对于 BLE 后台工作,在 Xcode 中启用 capability „Uses Bluetooth LE accessories” 并将 „bluetooth-central” 键添加到 UIBackgroundModes。对于外围角色 — „bluetooth-peripheral”。在管理器初始化时指定 restoreIdentifier 以进行状态恢复。没有这些设置,后台应用不会收到 BLE 事件并失去连接。
主要原因:CBCentralManager.state != .poweredOn(蓝牙已关闭或未授权)、委托未设置、设备超出范围或不发送广播包。检查 Info.plist 中的 NSBluetoothAlwaysUsageDescription 权限、centralManagerDidUpdateState 中的蓝牙状态,并确保 scanForPeripherals 仅在 .poweredOn 时调用。
是的,Core Bluetooth 支持同时连接到多个 BLE 设备。每个 CBPeripheral 通过自己的委托独立管理。iOS 在系统级别限制同时 BLE 连接的数量(iPhone 通常为 5–7)。对于 1:N 场景(例如,具有 10 个追踪器的健身中心),需要排队和循环服务外围设备。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。