Build direct Bluetooth Low Energy central or peripheral workflows with Core Bluetooth, including GATT discovery, state restoration, MTU sizing, and background modes. Use for BLE scanning, peripheral connection, characteristic reads/writes/notifications, or peripheral advertisement.
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Implement Bluetooth Low Energy (BLE) communication on iOS using CBCentralManager (connecting to accessories) and CBPeripheralManager (advertising as an accessory). Targets Swift 6.4 / iOS 26+.
Declare NSBluetoothAlwaysUsageDescription in Info.plist. For background execution, enable capabilities in Signing & Capabilities > Background Modes:
bluetooth-central)bluetooth-peripheral)<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app requires Bluetooth to connect to external fitness sensors.</string>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>| Feature | Central (CBCentralManager) | Peripheral (CBPeripheralManager) |
|---|---|---|
| Primary Task | Scans, connects, and consumes GATT services | Publishes services, advertises, responds to requests |
| Discovery | scanForPeripherals(withServices:options:) | startAdvertising(_:) |
| Data Read/Write | readValue(for:) / writeValue(_:for:type:) | respond(to:withResult:) |
| Updates | Subscribes with setNotifyValue(true, for:) | updateValue(_:for:onSubscribedCentrals:) |
| Queue | Dedicated serial DispatchQueue | Dedicated serial DispatchQueue |
.poweredOn: Never call scan, connect, or advertise until centralManagerDidUpdateState(_:) reports .poweredOn.CBPeripheral instances returned in didDiscover. If released, connection drops immediately.CBUUID filters is disabled by iOS to preserve battery.[CBUUID] arrays to discoverServices and discoverCharacteristics rather than nil to avoid slow full-GATT enumeration..withResponse for acknowledged writes (peripheral(_:didWriteValueFor:error:)); use .withoutResponse only when canSendWriteWithoutResponse is verified.CBCentralManagerOptionRestoreIdentifierKey during manager initialization to allow iOS to relaunch the app in the background when a Bluetooth event occurs. Handle restoration in centralManager(_:willRestoreState:).peripheral.maximumWriteValueLength(for:) before sending large payloads. The default BLE MTU is 23 bytes (20 payload bytes). Do not assume 512-byte MTU without checking.@Observable BLE manager, read SwiftUI BLE Integration.centralManagerDidUpdateState(_:) transitions to .poweredOn.CBPeripheral reference during connection, leading to silent drops.CBUUIDs in background mode (system ignores unfiltered background scans).canSendWriteWithoutResponse, causing silent packet drops during burst writes.NSBluetoothAlwaysUsageDescription provided in Info.plistUIBackgroundModes configured (bluetooth-central / bluetooth-peripheral).poweredOn before issuing commands[CBUUID].withResponse vs .withoutResponse)willRestoreState@MainActormaximumWriteValueLengththienqo/ios-skills
6bf8b62
Canonical home
since May 23, 2026
Also appears in
on Oct 29, 2026
since May 22, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.