最近のCore BluetoothのOSS
2022年1月25日現在。
AsyncBluetooth
11スター、最終更新は 14 hours ago。
oobaさんが使っていたのを機に知った。
こんな感じで、async/awaitを使って書ける。
スキャン
let centralManager = CentralManager()
try await centralManager.waitUntilReady()
var scanDataStream = try await centralManager.scanForPeripherals(withServices: nil)
for await scanData in scanDataStream {
// Check scan data...
}
await centralManager.stopScan()
接続
try await centralManager.connect(peripheral, options: nil)
Read
let value: String? = try await peripheral.readValue(
forCharacteristicWithUUID: UUID(uuidString: "")!,
ofServiceWithUUID: UUID(uuidString: "")!
)
RequirementsとしてiOS 15+。
サンプル(別リポジトリにある)はSwiftUIで書かれている。
Xcode 13.2以降を使えばiOS 13+で使用できる?
AsyncBluetoothは前述の通りiOS 15+となっているが、Xcode 13.2(厳密にはXcode 13.2.1)以降でビルドすればiOS 13以上で利用可能になるのか?
結論から言うと、iOS 13では不可、iOS 14以上では利用可能。
ビルドしてみたところ、内部でLoggerというiOS 14/macOS 11で追加されたAPIを利用していて、そこで引っかかった。
public struct AsyncBluetooth {
static let commonLogger = Logger(
subsystem: Bundle(for: CentralManager.self).bundleIdentifier ?? "",
category: "common"
)
}
Package.swiftでiOS 14.0, macOS 11.0を指定してビルドしなおせば、iOS 14以上では利用可能になる。
let package = Package(
name: "AsyncBluetooth",
platforms: [
.macOS("11.0"),
.iOS("14.0")
],
(ちなみにサンプル内ではiOS 15のAPIを利用しているため、サンプルはそのままではiOS 14では利用できない。)
CombineCoreBluetooth
39スター。最終更新は2021年9月。
その名の通り、Combine + Core Bluetooth。
こんな感じで書ける。
// use whatever ids your peripheral advertises here
let serviceID = CBUUID(string: "0123")
let characteristicID = CBUUID(string: "4567")
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)
依存関係の設計にはpointfreeのアプローチを採用しているらしい。
RequirementsとしてはiOS 13+。
SwiftyBluetooth
145スター、最終更新は14days ago.
ということで、デリゲートじゃなくてクロージャで書けるようにするライブラリ。
SwiftyBluetooth.scanForPeripherals(withServiceUUIDs: nil, timeoutAfter: 15) { scanResult in
switch scanResult {
case .scanStarted:
// The scan started meaning CBCentralManager scanForPeripherals(...) was called
case .scanResult(let peripheral, let advertisementData, let RSSI):
// A peripheral was found, your closure may be called multiple time with a .ScanResult enum case.
// You can save that peripheral for future use, or call some of its functions directly in this closure.
case .scanStopped(let error):
// The scan stopped, an error is passed if the scan stopped unexpectedly
}
}
iOS 10+。
SwiftyTeeth
19スター、最終更新は2021年9月。
コンセプトとしてはSwiftyBluetoothと同様にクロージャベースで書けるようにすることと、簡単に扱えることを目指したものらしい。
RequirementsはiOS 10+。
今ならどれを使うか?
個人的には、Core Bluetooth関連のOSSは十分に枯れていないことが多い印象で、プロダクトとして作り込む場合はサードパーティ製ライブラリは使わず素のCore Bluetoothを使うようにしている。
デモやプロトタイプであれば、AsyncBluetoothを利用してみると思う。(前述の通り、iOS 15+という厳しい制約はXcode 13.2を利用すれば解消するので)
最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/