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 извиквания се игнорират от системата. Разработчикът трябва да проверява state преди всяко сканиране и свързване. Преходът от .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) незабавно се стартира откриване на услуги — това е задължителна стъпка преди каквито и да било 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. След откриване на услуги и характеристики, централното устройство може да извърши три типа операции: четене на стойност на характеристика, запис на стойност и абониране за известия/индикации. Всяка операция е асинхронна и връща резултата чрез съответния CBPeripheralDelegate делегат.
Четене се извършва чрез извикване на readValueForCharacteristic:. Стойността пристига в peripheral:didUpdateValueForCharacteristic:error:. Важно: четенето връща текущата стойност от устройството, а не кеширана. Ако устройството не поддържа четене (свойство .read), извикването ще върне грешка. За големи стойности (по-големи от MTU) BLE автоматично фрагментира и сглобява данни на GATT ниво.
Запис се извършва чрез writeValue:forCharacteristic:type:. BLE поддържа два модела на запис: withResponse (надежден, с потвърждение) и withoutResponse (бърз, без потвърждение). Свойството CBCharacteristic.properties определя наличните типове запис. Максималният размер на един пакет за запис е ограничен от 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 откриване
peripheral.discoverServices(nil)
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("Bluetooth готов след възстановяване")
}
}
}
В конфигурацията BLECentralWithRestoration ключът CBCentralManagerOptionRestoreIdentifierKey активира запазване на състоянието. Ако приложението е било прекратено от iOS (например поради липса на памет), при следващото стартиране centralManager:willRestoreState: получава списък с предварително свързани CBPeripheral. Приложението възстановява делегатите и извършва повторно откриване на услуги — потребителят не забелязва прекъсване на връзката. Без 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също