CombineCoreBluetooth 是一个库,它桥接了 Apple 的 CoreBluetooth
框架和 Apple 的 Combine
框架,从而可以订阅执行蓝牙操作,同时订阅这些操作结果的 Publisher,而不是依赖于实现委托并手动过滤所需的結果。
(如果您使用 Carthage,或者如果您想打开项目来玩演示应用程序,您将需要使用 Xcode 16)
将此行添加到您的 Package.swift 文件中的 dependencies 列表:
.package(name: "CombineCoreBluetooth", url: "https://github.com/StarryInternet/CombineCoreBluetooth.git", from: "0.8.0"),
将此行添加到您的 Podfile 文件:
pod 'CombineCoreBluetooth'
将此行添加到您的 Cartfile 文件:
github "StarryInternet/CombineCoreBluetooth"
该库深受 pointfree.co 的方法 的启发,用于设计依赖项,但进行了一些自定义。许多异步操作会返回它们自己的 Publisher
或公开您可以订阅的长期存在的 publisher。
除了启用该库以提供以 Combine 为中心的 API 所需的内容之外,该库不维护任何其他状态。 这意味着您负责维护任何必要的状态,包括持有通过 CentralManager
类型发现和连接到的任何 Peripheral
。
要扫描外围设备,就像在普通的 CoreBluetooth 中一样,您调用 scanForPeripherals(withServices:options:)
方法。但是,在该库的 CentralManager
类型上,它返回 PeripheralDiscovery
值的 publisher。如果您想存储外围设备以供以后使用,您可以订阅返回的 publisher,如下所示:
let serviceID = CBUUID(string: "0123")
centralManager.scanForPeripherals(withServices: [serviceID])
.first()
.assign(to: \.peripheralDiscovery, on: self) // property of type PeripheralDiscovery
.store(in: &cancellables)
要执行诸如从特征中获取值之类的操作,例如,您可以在 Peripheral
类型上调用以下方法并订阅生成的 Publisher
:
// use whatever ids your peripheral advertises here
let characteristicID = CBUUID(string: "4567")
peripheralDiscovery.peripheral
.readValue(forCharacteristic: characteristicID, inService: serviceID)
.sink(receiveCompletion: { completion in
// handle any potential errors here
}, receiveValue: { data in
// handle data from characteristic here, or add more publisher methods to map and transform it.
})
.store(in: &cancellables)
readValue
中返回的 publisher 只会将与服务和特征 ID 匹配的值传递给任何订阅者,因此您无需担心任何过滤逻辑。请注意,如果 Peripheral
从未通过蓝牙从此特征接收到值,它将永远不会将值发送到 publisher 中,因此如果您的用例需要,您可能需要添加超时。
CoreBluetooth
中的所有主要类型都应该在该库中可用,包装在它们自己的类型中以提供以 Combine
为中心的 API。该库已经在生产环境中针对大多数与 CentralManager
相关的操作进行了测试。使用 PeripheralManager
类型也支持充当蓝牙外围设备的应用程序,但那方面没有经过严格的测试。