Core Bluetooth — фреймворк Apple для взаємодії з Bluetooth Low Energy на iOS, iPadOS та macOS. Фреймворк надає повний набір API для роботи в обох ролях BLE: центральний пристрій (CBCentralManager) для сканування та підключення до периферії, і периферійний пристрій (CBPeripheralManager) для емуляції BLE-сервера. Core Bluetooth абстрагує стек протоколу BLE від фізичного радіо до прикладного GATT-профілю. За даними Apple Developer, 2026, Core Bluetooth — єдиний офіційний API Apple для BLE-розробки, що підтримує BLE 4.0–5.4 з extended advertising, 2M PHY та LE Audio.
Головне
Core Bluetooth розділяє стек BLE на дві логічні ролі, визначені специфікацією Bluetooth SIG. Роль центрального пристрою (Central) представлена класом CBCentralManager — він ініціює сканування, встановлює з’єднання та керує списком підключених CBPeripheral. Роль периферійного пристрою (Peripheral) представлена CBPeripheralManager — він публікує сервіси та характеристики, відповідає на запити центрального та надсилає сповіщення. Одна iOS-сесія може одночасно працювати в обох ролях на різних BLE-радіо, але типовий додаток використовує одну роль.
Архітектура Core Bluetooth включає п’ять ключових абстракцій. CBCentralManager керує станом Bluetooth-адаптера пристрою: poweredOn (готовий до роботи), poweredOff (Bluetooth вимкнено), unauthorized (немає дозволу), unsupported (BLE недоступний). CBPeripheral представляє віддалений BLE-пристрій з його UUID, іменем, RSSI та GATT-ієрархією. CBService — логічна група характеристик. CBCharacteristic — точка даних для читання/запису/сповіщень. CBPeripheralManager створює локальний GATT-сервер для емуляції периферії.
| Клас | Роль | Основні методи |
|---|---|---|
| CBCentralManager | Центральний пристрій | scanForPeripherals, connect, cancelPeripheralConnection, retrievePeripherals |
| CBPeripheral | Віддалена периферія | discoverServices, discoverCharacteristics, readValue, writeValue, setNotifyValue |
| CBPeripheralManager | Локальна периферія | addService, removeService, startAdvertising, respondToRequest, updateValue |
| CBCentral | Віддалений центральний | maximumUpdateValueLength, identifier, ancsAuthorized |
Стани CBCentralManager керують усіма BLE-операціями. При запуску додатка centralManagerDidUpdateState викликається з поточним станом Bluetooth. Якщо стан не .poweredOn, будь-які BLE-виклики ігноруються системою. Розробник зобов’язаний перевіряти стан перед кожним скануванням та підключенням. Перехід з .poweredOff у .poweredOn відбувається при увімкненні Bluetooth у налаштуваннях iOS — делегат отримує повторний виклик, і додаток може відновити сканування.
CBCentralManager — точка входу для всіх BLE-операцій з боку центрального пристрою. Ініціалізація приймає делегат (CBCentralManagerDelegate) та DispatchQueue — рекомендація Apple використовувати main queue для простоти або serial queue для продуктивності. Після ініціалізації фреймворк автоматично перевіряє стан Bluetooth та викликає centralManagerDidUpdateState: — перший обов’язковий делегат для обробки.
Сканування запускається методом scanForPeripheralsWithServices:options:. Перший параметр — масив CBUUID сервісів для фільтрації: якщо відомі UUID цікавих сервісів, передача їх скорочує енергоспоживання та час пошуку. Якщо nil, виявляються всі BLE-пристрої в зоні дії. Опції включають .allowDuplicatesKey (повторні виявлення одного пристрою) та .solicitedServiceUUIDsKey (для сервісів, що публікуються на централі).
import CoreBluetooth
class BLECentral: NSObject {
private var centralManager: CBCentralManager!
private var discoveredPeripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: .main)
}
// Почати BLE-сканування
func startScan() {
guard centralManager.state == .poweredOn else {
print("Bluetooth недоступний")
return
}
// Сканувати всі пристрої (nil = без фільтра)
centralManager.scanForPeripherals(withServices: nil,
options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
}
// Зупинити сканування
func stopScan() {
centralManager.stopScan()
}
// Підключитися до вибраного пристрою
func connect(to peripheral: CBPeripheral) {
centralManager.connect(peripheral, options: nil)
}
}
// MARK: - CBCentralManagerDelegate
extension BLECentral: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
startScan()
}
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi: NSNumber) {
if !discoveredPeripherals.contains(where: { $0.identifier == peripheral.identifier }) {
discoveredPeripherals.append(peripheral)
print("Found devices: \(peripheral.name ?? "Unknown"), RSSI: \(rssi)")
}
}
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
print("Connected: \(peripheral.identifier)")
peripheral.delegate = self
peripheral.discoverServices(nil)
}
func centralManager(_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?) {
print("Disconnected: \(peripheral.identifier)")
}
}
Клас BLECentral демонструє повний цикл сканування та підключення BLE-пристроїв. centralManagerDidUpdateState запускає сканування при увімкненому Bluetooth. didDiscoverPeripheral збирає знайдені пристрої в масив discoveredPeripherals з дедуплікацією за identifier. Після підключення (didConnect) негайно запускається discovery сервісів — це обов’язковий крок перед будь-якими GATT-операціями.
CBPeripheralManager — клас для емуляції BLE-периферійного пристрою на iOS. Додаток у ролі периферії може публікувати свої сервіси та характеристики, приймати вхідні запити на читання/запис від центрального пристрою та надсилати сповіщення. CBPeripheralManager використовується для BLE-аксесуарів, що емулюються iPhone: пульти, клавіатури, трекери, IoT-шлюзи.
Життєвий цикл CBPeripheralManager починається з ініціалізації та делегата CBPeripheralManagerDelegate. Після підтвердження poweredOn через peripheralManagerDidUpdateState: публікуються сервіси (addService:) та запускається реклама (startAdvertising:). Рекламні дані CBAdvertisementData включають локальне ім’я (CBAdvertisementDataLocalNameKey), UUID сервісів (CBAdvertisementDataServiceUUIDsKey) та рівень потужності (CBAdvertisementDataTxPowerLevelKey). Максимальний розмір рекламного пакета — 31 байт для BLE 4.0, 251 байт для extended advertising BLE 5.0+.
// BLE периферія на iOS через CBPeripheralManager
class BLEPeripheral: NSObject {
private var peripheralManager: CBPeripheralManager!
let serviceUUID = CBUUID(string: "1234")
let characteristicUUID = CBUUID(string: "5678")
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: .main)
}
// Опублікувати сервіс з характеристикою
func setupService() {
let characteristic = CBMutableCharacteristic(
type: characteristicUUID,
properties: [.read, .write, .notify],
value: nil,
permissions: [.readable, .writeable]
)
let service = CBMutableService(type: serviceUUID, primary: true)
service.characteristics = [characteristic]
peripheralManager.add(service)
}
// Запустити рекламу
func startAdvertising() {
let advertisementData: [String: Any] = [
CBAdvertisementDataLocalNameKey: "My BLE Device",
CBAdvertisementDataServiceUUIDsKey: [serviceUUID]
]
peripheralManager.startAdvertising(advertisementData)
}
}
// MARK: - CBPeripheralManagerDelegate
extension BLEPeripheral: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
setupService()
}
}
func peripheralManager(_ peripheral: CBPeripheralManager,
didAdd service: CBService,
error: Error?) {
if error == nil {
startAdvertising()
}
}
// Обробити запит на читання
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveRead request: CBATTRequest) {
let data = "CurrentValue".data(using: .utf8)!
request.value = data
peripheralManager.respond(to: request, withResult: .success)
}
// Обробити запит на запис
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveWrite requests: [CBATTRequest]) {
for request in requests {
if let value = request.value {
print("Write: \(value)")
}
}
peripheralManager.respond(to: requests.first!, withResult: .success)
}
}
Клас BLEPeripheral створює BLE-сервер з однією характеристикою, що підтримує читання, запис та сповіщення. Після ініціалізації peripheralManagerDidUpdateState публікує сервіс через addService:, потім запускає рекламу через startAdvertising:. Обробники didReceiveRead та didReceiveWrite відповідають на вхідні GATT-запити від центрального пристрою. Для надсилання сповіщень використовується метод updateValue:forCharacteristic:onSubscribedCentrals:.
GATT-операції (Generic Attribute Profile) — основа обміну даними в Core Bluetooth. Після discovery сервісів та характеристик центральний пристрій може виконувати три типи операцій: читання значення характеристики, запис значення та підписку на сповіщення/індикації. Кожна операція асинхронна і повертає результат через відповідний делегат CBPeripheralDelegate.
Читання виконується викликом readValueForCharacteristic:. Значення приходить у peripheral:didUpdateValueForCharacteristic:error:. Важливо: читання повертає поточне значення з пристрою, а не кешоване. Якщо пристрій не підтримує читання (властивість .read), виклик поверне помилку. Для великих значень (більше MTU) BLE автоматично фрагментує та збирає дані на рівні GATT.
Запис виконується викликом writeValue:forCharacteristic:type:. BLE підтримує дві моделі запису: withResponse (надійна, з підтвердженням) та withoutResponse (швидка, без підтвердження). Властивість CBCharacteristic.properties визначає доступні типи запису. Максимальний розмір одного write-пакета обмежений MTU: 23 байти для BLE 4.0 (20 байт корисних даних + 3 байти заголовка), до 247 байт для BLE 5.0 з extended MTU (MTU 251).
Сповіщення активуються викликом setNotifyValue:true forCharacteristic:. Після підписки периферія автоматично надсилає оновлення через peripheral:didUpdateValueForCharacteristic: щоразу, коли значення характеристики змінюється. Для вимкнення сповіщень викликається setNotifyValue:false forCharacteristic:. Core Bluetooth автоматично керує CCCD-дескриптором на периферії.
| Операція | Метод | Делегат | Тип передачі |
|---|---|---|---|
| Читання | readValueForCharacteristic: | didUpdateValueForCharacteristic | Polling (запит-відповідь) |
| Запис withResponse | writeValue:forCharacteristic:type:withResponse | didWriteValueForCharacteristic | З підтвердженням |
| Запис withoutResponse | writeValue:forCharacteristic:type:withoutResponse | Немає делегата | Без підтвердження |
| Сповіщення | setNotifyValue:true forCharacteristic: | didUpdateNotificationStateForCharacteristic + didUpdateValueForCharacteristic | Push від периферії |
фоновий режим Core Bluetooth дозволяє BLE-додатку продовжувати сканування, підтримувати з’єднання та отримувати сповіщення при знаходженні у фоні. Для активації потрібно: увімкнути capability «Uses Bluetooth LE accessories» у Xcode (Info.plist → Required background modes → App communicates using Core Bluetooth) та додати ключ «bluetooth-central» до UIBackgroundModes. Для периферійної ролі — «bluetooth-peripheral».
State Restoration — механізм Core Bluetooth для відновлення стану BLE-з’єднань після перезапуску додатка системою iOS. При активації фонового режиму та вказанні restoreIdentifier в ініціалізації CBCentralManager або CBPeripheralManager, iOS зберігає стан BLE-стека при завершенні додатка та відновлює його при наступному запуску. Делегат centralManager:willRestoreState: отримує словник зі збереженими CBPeripheral та очікуваними з’єднаннями.
// Конфігурація Core Bluetooth з State Restoration
class BLECentralWithRestoration: NSObject {
let restoreIdentifier = "com.app.blecentral"
private var centralManager: CBCentralManager!
override init() {
super.init()
let options: [String: Any] = [
CBCentralManagerOptionRestoreIdentifierKey: restoreIdentifier,
CBCentralManagerOptionShowPowerAlertKey: true
]
centralManager = CBCentralManager(delegate: self,
queue: nil,
options: options)
}
}
extension BLECentralWithRestoration: CBCentralManagerDelegate {
// Відновити стан після перезапуску
func centralManager(_ central: CBCentralManager,
willRestoreState dict: [String : Any]) {
if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
as? [CBPeripheral] {
for peripheral in peripherals {
peripheral.delegate = self
// Відновити GATT-discovery
peripheral.discoverServices(nil)
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("Bluetooth готовий після відновлення")
}
}
}
У конфігурації BLECentralWithRestoration ключ CBCentralManagerOptionRestoreIdentifierKey активує збереження стану. Якщо додаток був завершений iOS (наприклад, через нестачу пам’яті), при наступному запуску centralManager:willRestoreState: отримує список раніше підключених CBPeripheral. Додаток відновлює делегати та виконує повторний discovery сервісів — користувач не помічає розриву з’єднання. Без State Restoration всі BLE-сесії втрачаються при завершенні додатка.
Повний приклад BLE-додатку на Swift об’єднує центральний та периферійний пристрої в одному проекті. Додаток може працювати в двох режимах: виявляти та підключатися до BLE-пристроїв (Central) або емулювати BLE-аксесуар (Peripheral). Нижче наведена архітектура із загальним менеджером BLE, що вибирає роль при старті.
// Універсальний BLE-менеджер для централі та периферії
class BLEManager {
enum Role {
case central
case peripheral
}
private let role: Role
private var centralManager: CBCentralManager?
private var peripheralManager: CBPeripheralManager?
let advertisedServiceUUID = CBUUID(string: "A001")
init(role: Role) {
self.role = role
switch role {
case .central:
centralManager = CBCentralManager(delegate: nil, queue: .main)
case .peripheral:
peripheralManager = CBPeripheralManager(delegate: nil, queue: .main)
}
}
// Центральний пристрій: сканування
func scanForDevices() {
centralManager?.scanForPeripherals(withServices: nil, options: nil)
}
// Периферійний пристрій: реклама
func advertiseService() {
let data: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [advertisedServiceUUID]
]
peripheralManager?.startAdvertising(data)
}
}
// Використання при старті
let isCentral = UserDefaults.standard.bool(forKey: "isCentral")
let manager = BLEManager(role: isCentral ? .central : .peripheral)
if isCentral {
manager.scanForDevices()
} else {
manager.advertiseService()
}
Менеджер BLEManager вибирає роль при ініціалізації та створює відповідний Manager (CBCentralManager або CBPeripheralManager). Прапорець ролі може зберігатися в UserDefaults або передаватися через сервер конфігурації. Такий підхід дозволяє BLE-додатку адаптуватися під сценарій використання: на точці продажу iPhone працює як централь для сканування платіжних терміналів, на IoT-шлюзі — як периферія для збору даних з датчиків.
Часті запитання
Core Bluetooth — фреймворк Apple для BLE-розробки на iOS, iPadOS та macOS. Надає API для роботи центрального (CBCentralManager) та периферійного (CBPeripheralManager) пристроїв. Підтримує BLE 4.0–5.4, extended advertising, 2M PHY та LE Audio. Core Bluetooth — єдиний офіційний API Apple для BLE-комунікації, обов’язковий для всіх iOS-додатків, що працюють з Bluetooth Low Energy.
CBCentralManager — клас для роботи в ролі центрального пристрою: сканує BLE-периферію, встановлює з’єднання, читає та пише характеристики. CBPeripheralManager — клас для роботи в ролі периферії: публікує сервіси, відповідає на запити читання/запису та надсилає сповіщення. Один iPhone може працювати в двох ролях одночасно через різні інстанси менеджерів.
Для фонової BLE-роботи увімкніть capability «Uses Bluetooth LE accessories» у Xcode та додайте ключ «bluetooth-central» до UIBackgroundModes. Для периферійної ролі — «bluetooth-peripheral». Вкажіть restoreIdentifier при ініціалізації менеджера для State Restoration. Без цих налаштувань додаток у фоні не отримує BLE-події та втрачає з’єднання.
Основні причини: CBCentralManager.state != .poweredOn (Bluetooth вимкнено або не авторизовано), делегат не встановлено, пристрій поза зоною дії або не надсилає рекламні пакети. Перевірте дозвіл NSBluetoothAlwaysUsageDescription у Info.plist, статус Bluetooth у centralManagerDidUpdateState та переконайтеся, що scanForPeripherals викликається тільки при .poweredOn.
Так, Core Bluetooth підтримує одночасне підключення до кількох BLE-пристроїв. Кожен CBPeripheral керується незалежно через власний делегат. iOS обмежує кількість одночасних BLE-з’єднань на рівні системи (зазвичай 5–7 для iPhone). Для сценаріїв 1:N (наприклад, фітнес-центр з 10 трекерами) потрібна постановка в чергу та циклічне обслуговування периферій.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також