BLESwift
BLESwift is an open source BLE library I created that makes Bluetooth code read the way you'd describe the task: wait for the radio, find a device, connect, stream readings. Top to bottom, no nesting, with every failure point an ordinary try.
It ships alongside BLESwiftCLI, which provides ble, a macOS command-line tool for scanning, connecting, inspecting, and pairing with peripherals, built entirely on BLESwift.
Why I Built It
CoreBluetooth's delegate-based API scatters simple logic across half a dozen callbacks, and the wrapper libraries most apps rely on predate async/await, actors, and Swift 6 strict concurrency. I wanted a library where the compiler enforces thread safety instead of a code comment asking you to be careful.
Key Features
- Actor-isolated by design:
Centralis an actor whose isolation is tied to the same serial queue CoreBluetooth delivers callbacks on, so every event arrives already on the actor's executor - no thread hops, no locks - Multi-peripheral connections: Connect to as many peripherals as you like, each with its own connection lifecycle and GATT state
- Declarative reconnection: A
ReconnectPolicytype replaces manual retry bookkeeping with.never,.always(maxAttempts:backoff:), or fully custom backoff - Testing without hardware: A
BLESwiftTestSupportproduct shipsFakeCentralandFakePeripheral, scriptable stand-ins that let you test BLE flows with no radio required - Broad platform support: iOS 18, macOS 15, watchOS 11, tvOS 18, and visionOS 2, with swift-log as the only dependency
The CLI
The ble tool is both a debugging companion and the existence proof for the library: ble scan shows a live table of nearby devices, ble inspect dumps a full GATT tree with standard attributes labeled by name, and ble read, ble write, ble pair, and ble l2cap cover the rest. Everything prints data to stdout and status to stderr, so ble scan --json | jq works the way you'd hope.