core-bluetooth

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Core Bluetooth

Core Bluetooth

Scan for, connect to, and exchange data with Bluetooth Low Energy (BLE) devices. Covers the central role (scanning and connecting to peripherals), the peripheral role (advertising services), background modes, and state restoration. Targets Swift 6.2 / iOS 26+.
扫描、连接低功耗蓝牙(BLE)设备并与之交换数据。涵盖中心角色(扫描和连接外设)、外设角色(广播服务)、后台模式以及状态恢复功能。适配Swift 6.2 / iOS 26+版本。

Contents

目录

Setup

配置

Info.plist Keys

Info.plist 键值

KeyPurpose
NSBluetoothAlwaysUsageDescription
Required. Explains why the app uses Bluetooth
UIBackgroundModes
with
bluetooth-central
Background scanning and connecting
UIBackgroundModes
with
bluetooth-peripheral
Background advertising
用途
NSBluetoothAlwaysUsageDescription
必填项,说明应用使用蓝牙的原因
包含
bluetooth-central
UIBackgroundModes
后台扫描与连接
包含
bluetooth-peripheral
UIBackgroundModes
后台广播

Bluetooth Authorization

蓝牙授权

iOS prompts for Bluetooth permission automatically when you create a
CBCentralManager
or
CBPeripheralManager
. The usage description from
NSBluetoothAlwaysUsageDescription
is shown in the permission dialog.
当你创建
CBCentralManager
CBPeripheralManager
时,iOS会自动请求蓝牙权限。权限弹窗中会显示
NSBluetoothAlwaysUsageDescription
设置的使用说明。

Central Role: Scanning

中心角色:扫描

Creating the Central Manager

创建中心管理器

Always wait for the
poweredOn
state before scanning.
swift
import CoreBluetooth

final class BluetoothManager: NSObject, CBCentralManagerDelegate {
    private var centralManager: CBCentralManager!
    private var discoveredPeripheral: CBPeripheral?

    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            startScanning()
        case .poweredOff:
            // Bluetooth is off -- prompt user to enable
            break
        case .unauthorized:
            // App not authorized for Bluetooth
            break
        case .unsupported:
            // Device does not support BLE
            break
        case .resetting, .unknown:
            break
        @unknown default:
            break
        }
    }
}
始终等待
poweredOn
状态后再开始扫描。
swift
import CoreBluetooth

final class BluetoothManager: NSObject, CBCentralManagerDelegate {
    private var centralManager: CBCentralManager!
    private var discoveredPeripheral: CBPeripheral?

    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            startScanning()
        case .poweredOff:
            // Bluetooth is off -- prompt user to enable
            break
        case .unauthorized:
            // App not authorized for Bluetooth
            break
        case .unsupported:
            // Device does not support BLE
            break
        case .resetting, .unknown:
            break
        @unknown default:
            break
        }
    }
}

Scanning for Peripherals

扫描外设

Scan for specific service UUIDs to save power. Pass
nil
to discover all peripherals (not recommended in production).
swift
let heartRateServiceUUID = CBUUID(string: "180D")

func startScanning() {
    centralManager.scanForPeripherals(
        withServices: [heartRateServiceUUID],
        options: [CBCentralManagerScanOptionAllowDuplicatesKey: false]
    )
}

func centralManager(
    _ central: CBCentralManager,
    didDiscover peripheral: CBPeripheral,
    advertisementData: [String: Any],
    rssi RSSI: NSNumber
) {
    guard RSSI.intValue > -70 else { return } // Filter weak signals

    // IMPORTANT: Retain the peripheral -- it will be deallocated otherwise
    discoveredPeripheral = peripheral
    centralManager.stopScan()
    centralManager.connect(peripheral, options: nil)
}
扫描特定服务UUID以节省电量。传入
nil
会发现所有外设(生产环境不推荐)。
swift
let heartRateServiceUUID = CBUUID(string: "180D")

func startScanning() {
    centralManager.scanForPeripherals(
        withServices: [heartRateServiceUUID],
        options: [CBCentralManagerScanOptionAllowDuplicatesKey: false]
    )
}

func centralManager(
    _ central: CBCentralManager,
    didDiscover peripheral: CBPeripheral,
    advertisementData: [String: Any],
    rssi RSSI: NSNumber
) {
    guard RSSI.intValue > -70 else { return } // Filter weak signals

    // IMPORTANT: Retain the peripheral -- it will be deallocated otherwise
    discoveredPeripheral = peripheral
    centralManager.stopScan()
    centralManager.connect(peripheral, options: nil)
}

Central Role: Connecting

中心角色:连接

swift
func centralManager(
    _ central: CBCentralManager,
    didConnect peripheral: CBPeripheral
) {
    peripheral.delegate = self
    peripheral.discoverServices([heartRateServiceUUID])
}

func centralManager(
    _ central: CBCentralManager,
    didFailToConnect peripheral: CBPeripheral,
    error: Error?
) {
    // Handle connection failure -- retry or inform user
    discoveredPeripheral = nil
}

func centralManager(
    _ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral,
    timestamp: CFAbsoluteTime,
    isReconnecting: Bool,
    error: Error?
) {
    if isReconnecting {
        // System is automatically reconnecting
        return
    }
    // Handle disconnection -- optionally reconnect
    discoveredPeripheral = nil
}
swift
func centralManager(
    _ central: CBCentralManager,
    didConnect peripheral: CBPeripheral
) {
    peripheral.delegate = self
    peripheral.discoverServices([heartRateServiceUUID])
}

func centralManager(
    _ central: CBCentralManager,
    didFailToConnect peripheral: CBPeripheral,
    error: Error?
) {
    // Handle connection failure -- retry or inform user
    discoveredPeripheral = nil
}

func centralManager(
    _ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral,
    timestamp: CFAbsoluteTime,
    isReconnecting: Bool,
    error: Error?
) {
    if isReconnecting {
        // System is automatically reconnecting
        return
    }
    // Handle disconnection -- optionally reconnect
    discoveredPeripheral = nil
}

Discovering Services and Characteristics

发现服务与特征

Implement
CBPeripheralDelegate
to walk the service/characteristic tree.
swift
extension BluetoothManager: CBPeripheralDelegate {
    func peripheral(
        _ peripheral: CBPeripheral,
        didDiscoverServices error: Error?
    ) {
        guard let services = peripheral.services else { return }
        for service in services {
            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.properties.contains(.notify) {
                peripheral.setNotifyValue(true, for: characteristic)
            }
            if characteristic.properties.contains(.read) {
                peripheral.readValue(for: characteristic)
            }
        }
    }
}
实现
CBPeripheralDelegate
来遍历服务/特征树。
swift
extension BluetoothManager: CBPeripheralDelegate {
    func peripheral(
        _ peripheral: CBPeripheral,
        didDiscoverServices error: Error?
    ) {
        guard let services = peripheral.services else { return }
        for service in services {
            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.properties.contains(.notify) {
                peripheral.setNotifyValue(true, for: characteristic)
            }
            if characteristic.properties.contains(.read) {
                peripheral.readValue(for: characteristic)
            }
        }
    }
}

Common Service and Characteristic UUIDs

常见服务与特征UUID

ServiceUUIDCharacteristics
Heart Rate
180D
Heart Rate Measurement (
2A37
), Body Sensor Location (
2A38
)
Battery
180F
Battery Level (
2A19
)
Device Information
180A
Manufacturer Name (
2A29
), Model Number (
2A24
)
Generic Access
1800
Device Name (
2A00
), Appearance (
2A01
)
swift
let heartRateMeasurementUUID = CBUUID(string: "2A37")
let batteryLevelUUID = CBUUID(string: "2A19")
服务UUID特征
心率
180D
心率测量(
2A37
)、身体传感器位置(
2A38
)
电池
180F
电池电量(
2A19
)
设备信息
180A
制造商名称(
2A29
)、型号编号(
2A24
)
通用访问
1800
设备名称(
2A00
)、外观(
2A01
)
swift
let heartRateMeasurementUUID = CBUUID(string: "2A37")
let batteryLevelUUID = CBUUID(string: "2A19")

Reading, Writing, and Notifications

读取、写入与通知

Reading a Value

读取值

swift
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("Heart rate: \(heartRate) bpm")
    case CBUUID(string: "2A19"):
        let batteryLevel = data.first.map { Int($0) } ?? 0
        print("Battery: \(batteryLevel)%")
    default:
        break
    }
}

private func parseHeartRate(_ data: Data) -> Int {
    let flags = data[0]
    let is16Bit = (flags & 0x01) != 0
    if is16Bit {
        return Int(data[1]) | (Int(data[2]) << 8)
    } else {
        return Int(data[1])
    }
}
swift
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("Heart rate: \(heartRate) bpm")
    case CBUUID(string: "2A19"):
        let batteryLevel = data.first.map { Int($0) } ?? 0
        print("Battery: \(batteryLevel)%")
    default:
        break
    }
}

private func parseHeartRate(_ data: Data) -> Int {
    let flags = data[0]
    let is16Bit = (flags & 0x01) != 0
    if is16Bit {
        return Int(data[1]) | (Int(data[2]) << 8)
    } else {
        return Int(data[1])
    }
}

Writing a Value

写入值

swift
func writeValue(_ data: Data, to characteristic: CBCharacteristic,
                on peripheral: CBPeripheral) {
    if characteristic.properties.contains(.writeWithoutResponse) {
        peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
    } else if characteristic.properties.contains(.write) {
        peripheral.writeValue(data, for: characteristic, type: .withResponse)
    }
}

// Confirmation callback for .withResponse writes
func peripheral(
    _ peripheral: CBPeripheral,
    didWriteValueFor characteristic: CBCharacteristic,
    error: Error?
) {
    if let error {
        print("Write failed: \(error.localizedDescription)")
    }
}
swift
func writeValue(_ data: Data, to characteristic: CBCharacteristic,
                on peripheral: CBPeripheral) {
    if characteristic.properties.contains(.writeWithoutResponse) {
        peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
    } else if characteristic.properties.contains(.write) {
        peripheral.writeValue(data, for: characteristic, type: .withResponse)
    }
}

// Confirmation callback for .withResponse writes
func peripheral(
    _ peripheral: CBPeripheral,
    didWriteValueFor characteristic: CBCharacteristic,
    error: Error?
) {
    if let error {
        print("Write failed: \(error.localizedDescription)")
    }
}

Subscribing to Notifications

订阅通知

swift
// Subscribe
peripheral.setNotifyValue(true, for: characteristic)

// Unsubscribe
peripheral.setNotifyValue(false, for: characteristic)

// Confirmation
func peripheral(
    _ peripheral: CBPeripheral,
    didUpdateNotificationStateFor characteristic: CBCharacteristic,
    error: Error?
) {
    if characteristic.isNotifying {
        print("Now receiving notifications for \(characteristic.uuid)")
    }
}
swift
// Subscribe
peripheral.setNotifyValue(true, for: characteristic)

// Unsubscribe
peripheral.setNotifyValue(false, for: characteristic)

// Confirmation
func peripheral(
    _ peripheral: CBPeripheral,
    didUpdateNotificationStateFor characteristic: CBCharacteristic,
    error: Error?
) {
    if characteristic.isNotifying {
        print("Now receiving notifications for \(characteristic.uuid)")
    }
}

Peripheral Role: Advertising

外设角色:广播

Publish services from the local device using
CBPeripheralManager
.
swift
final class BLEPeripheralManager: NSObject, CBPeripheralManagerDelegate {
    private var peripheralManager: CBPeripheralManager!
    private let serviceUUID = CBUUID(string: "12345678-1234-1234-1234-123456789ABC")
    private let charUUID = CBUUID(string: "12345678-1234-1234-1234-123456789ABD")

    override init() {
        super.init()
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
    }

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        guard peripheral.state == .poweredOn else { return }
        setupService()
    }

    private func setupService() {
        let characteristic = CBMutableCharacteristic(
            type: charUUID,
            properties: [.read, .notify],
            value: nil,
            permissions: [.readable]
        )

        let service = CBMutableService(type: serviceUUID, primary: true)
        service.characteristics = [characteristic]
        peripheralManager.add(service)
    }

    func peripheralManager(
        _ peripheral: CBPeripheralManager,
        didAdd service: CBService,
        error: Error?
    ) {
        guard error == nil else { return }
        peripheralManager.startAdvertising([
            CBAdvertisementDataServiceUUIDsKey: [serviceUUID],
            CBAdvertisementDataLocalNameKey: "MyDevice"
        ])
    }
}
使用
CBPeripheralManager
从本地设备发布服务。
swift
final class BLEPeripheralManager: NSObject, CBPeripheralManagerDelegate {
    private var peripheralManager: CBPeripheralManager!
    private let serviceUUID = CBUUID(string: "12345678-1234-1234-1234-123456789ABC")
    private let charUUID = CBUUID(string: "12345678-1234-1234-1234-123456789ABD")

    override init() {
        super.init()
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
    }

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        guard peripheral.state == .poweredOn else { return }
        setupService()
    }

    private func setupService() {
        let characteristic = CBMutableCharacteristic(
            type: charUUID,
            properties: [.read, .notify],
            value: nil,
            permissions: [.readable]
        )

        let service = CBMutableService(type: serviceUUID, primary: true)
        service.characteristics = [characteristic]
        peripheralManager.add(service)
    }

    func peripheralManager(
        _ peripheral: CBPeripheralManager,
        didAdd service: CBService,
        error: Error?
    ) {
        guard error == nil else { return }
        peripheralManager.startAdvertising([
            CBAdvertisementDataServiceUUIDsKey: [serviceUUID],
            CBAdvertisementDataLocalNameKey: "MyDevice"
        ])
    }
}

Background BLE

BLE后台模式

Background Central Mode

后台中心模式

Add
bluetooth-central
to
UIBackgroundModes
. In the background:
  • Scanning continues but only for specific service UUIDs
  • CBCentralManagerScanOptionAllowDuplicatesKey
    is ignored (always
    false
    )
  • Discovery callbacks are coalesced and delivered in batches
UIBackgroundModes
中添加
bluetooth-central
。后台状态下:
  • 扫描继续执行,但仅针对特定服务UUID
  • CBCentralManagerScanOptionAllowDuplicatesKey
    会被忽略(始终为
    false
  • 发现回调会被合并并批量交付

Background Peripheral Mode

后台外设模式

Add
bluetooth-peripheral
to
UIBackgroundModes
. In the background:
  • Advertising continues but data is reduced to service UUIDs only
  • The local name is not included in background advertisements
UIBackgroundModes
中添加
bluetooth-peripheral
。后台状态下:
  • 广播继续执行,但数据仅保留服务UUID
  • 本地名称不会包含在后台广播中

State Restoration

状态恢复

State restoration allows the system to re-create your central or peripheral manager after your app is terminated and relaunched for a BLE event.
状态恢复允许系统在应用因BLE事件被终止并重新启动后,重新创建你的中心或外设管理器。

Central Manager State Restoration

中心管理器状态恢复

swift
// 1. Create with a restoration identifier
centralManager = CBCentralManager(
    delegate: self,
    queue: nil,
    options: [CBCentralManagerOptionRestoreIdentifierKey: "myCentral"]
)

// 2. Implement the restoration delegate method
func centralManager(
    _ central: CBCentralManager,
    willRestoreState dict: [String: Any]
) {
    if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
        as? [CBPeripheral] {
        for peripheral in peripherals {
            // Re-assign delegate and retain
            peripheral.delegate = self
            discoveredPeripheral = peripheral
        }
    }
}
swift
// 1. 使用恢复标识符创建
centralManager = CBCentralManager(
    delegate: self,
    queue: nil,
    options: [CBCentralManagerOptionRestoreIdentifierKey: "myCentral"]
)

// 2. 实现恢复代理方法
func centralManager(
    _ central: CBCentralManager,
    willRestoreState dict: [String: Any]
) {
    if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
        as? [CBPeripheral] {
        for peripheral in peripherals {
            // Re-assign delegate and retain
            peripheral.delegate = self
            discoveredPeripheral = peripheral
        }
    }
}

Peripheral Manager State Restoration

外设管理器状态恢复

swift
peripheralManager = CBPeripheralManager(
    delegate: self,
    queue: nil,
    options: [CBPeripheralManagerOptionRestoreIdentifierKey: "myPeripheral"]
)

func peripheralManager(
    _ peripheral: CBPeripheralManager,
    willRestoreState dict: [String: Any]
) {
    // Restore published services, advertising state, etc.
}
swift
peripheralManager = CBPeripheralManager(
    delegate: self,
    queue: nil,
    options: [CBPeripheralManagerOptionRestoreIdentifierKey: "myPeripheral"]
)

func peripheralManager(
    _ peripheral: CBPeripheralManager,
    willRestoreState dict: [String: Any]
) {
    // Restore published services, advertising state, etc.
}

Common Mistakes

常见错误

DON'T: Scan or connect before poweredOn

请勿:在poweredOn前扫描或连接

swift
// WRONG: Scanning immediately -- manager may not be ready
let manager = CBCentralManager(delegate: self, queue: nil)
manager.scanForPeripherals(withServices: nil) // May silently fail

// CORRECT: Wait for poweredOn in the delegate
func centralManagerDidUpdateState(_ central: CBCentralManager) {
    if central.state == .poweredOn {
        central.scanForPeripherals(withServices: [serviceUUID])
    }
}
swift
// WRONG: Scanning immediately -- manager may not be ready
let manager = CBCentralManager(delegate: self, queue: nil)
manager.scanForPeripherals(withServices: nil) // May silently fail

// CORRECT: Wait for poweredOn in the delegate
func centralManagerDidUpdateState(_ central: CBCentralManager) {
    if central.state == .poweredOn {
        central.scanForPeripherals(withServices: [serviceUUID])
    }
}

DON'T: Lose the peripheral reference

请勿:丢失外设引用

Core Bluetooth does not retain discovered peripherals. If you don't hold a strong reference, the peripheral is deallocated and the connection fails silently.
swift
// WRONG: No strong reference kept
func centralManager(_ central: CBCentralManager,
                    didDiscover peripheral: CBPeripheral, ...) {
    central.connect(peripheral) // peripheral may be deallocated
}

// CORRECT: Retain the peripheral
func centralManager(_ central: CBCentralManager,
                    didDiscover peripheral: CBPeripheral, ...) {
    self.discoveredPeripheral = peripheral // Strong reference
    central.connect(peripheral)
}
Core Bluetooth不会保留已发现的外设。如果不持有强引用,外设会被释放,连接将静默失败。
swift
// WRONG: No strong reference kept
func centralManager(_ central: CBCentralManager,
                    didDiscover peripheral: CBPeripheral, ...) {
    central.connect(peripheral) // peripheral may be deallocated
}

// CORRECT: Retain the peripheral
func centralManager(_ central: CBCentralManager,
                    didDiscover peripheral: CBPeripheral, ...) {
    self.discoveredPeripheral = peripheral // Strong reference
    central.connect(peripheral)
}

DON'T: Scan for nil services in production

请勿:生产环境中扫描nil服务

swift
// WRONG: Discovers every BLE device in range -- drains battery
centralManager.scanForPeripherals(withServices: nil)

// CORRECT: Specify the service UUIDs you need
centralManager.scanForPeripherals(withServices: [targetServiceUUID])
swift
// WRONG: Discovers every BLE device in range -- drains battery
centralManager.scanForPeripherals(withServices: nil)

// CORRECT: Specify the service UUIDs you need
centralManager.scanForPeripherals(withServices: [targetServiceUUID])

DON'T: Assume connection order or timing

请勿:假设连接顺序或时机

swift
// WRONG: Assuming immediate connection
centralManager.connect(peripheral)
discoverServicesNow() // Peripheral not connected yet

// CORRECT: Discover services in the didConnect callback
func centralManager(_ central: CBCentralManager,
                    didConnect peripheral: CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices([serviceUUID])
}
swift
// WRONG: Assuming immediate connection
centralManager.connect(peripheral)
discoverServicesNow() // Peripheral not connected yet

// CORRECT: Discover services in the didConnect callback
func centralManager(_ central: CBCentralManager,
                    didConnect peripheral: CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices([serviceUUID])
}

DON'T: Write to a characteristic without checking properties

请勿:未检查属性就写入特征

swift
// WRONG: Crashes or silently fails if write is unsupported
peripheral.writeValue(data, for: characteristic, type: .withResponse)

// CORRECT: Check properties first
if characteristic.properties.contains(.write) {
    peripheral.writeValue(data, for: characteristic, type: .withResponse)
} else if characteristic.properties.contains(.writeWithoutResponse) {
    peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
}
swift
// WRONG: Crashes or silently fails if write is unsupported
peripheral.writeValue(data, for: characteristic, type: .withResponse)

// CORRECT: Check properties first
if characteristic.properties.contains(.write) {
    peripheral.writeValue(data, for: characteristic, type: .withResponse)
} else if characteristic.properties.contains(.writeWithoutResponse) {
    peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
}

Review Checklist

检查清单

  • NSBluetoothAlwaysUsageDescription
    added to Info.plist
  • All BLE operations gated on
    centralManagerDidUpdateState
    returning
    .poweredOn
  • Discovered peripherals retained with a strong reference
  • Scanning uses specific service UUIDs (not
    nil
    ) in production
  • CBPeripheralDelegate
    set before calling
    discoverServices
  • Characteristic properties checked before read/write/notify
  • Background mode (
    bluetooth-central
    or
    bluetooth-peripheral
    ) added if needed
  • State restoration identifier set if app needs relaunch-on-BLE-event support
  • willRestoreState
    delegate method implemented when using state restoration
  • Scanning stopped after discovering the target peripheral
  • Disconnection handled with optional automatic reconnect logic
  • Write type matches characteristic properties (
    .withResponse
    vs
    .withoutResponse
    )
  • 已在Info.plist中添加
    NSBluetoothAlwaysUsageDescription
  • 所有BLE操作均在
    centralManagerDidUpdateState
    返回
    .poweredOn
    后执行
  • 已通过强引用保留已发现的外设
  • 生产环境中扫描使用特定服务UUID(而非
    nil
  • 在调用
    discoverServices
    前已设置
    CBPeripheralDelegate
  • 读取/写入/通知前已检查特征属性
  • 按需添加了后台模式(
    bluetooth-central
    bluetooth-peripheral
  • 若应用需要支持BLE事件重启,已设置状态恢复标识符
  • 使用状态恢复时已实现
    willRestoreState
    代理方法
  • 发现目标外设后已停止扫描
  • 已处理断开连接逻辑,可选自动重连
  • 写入类型与特征属性匹配(
    .withResponse
    vs
    .withoutResponse

References

参考资料