Core Bluetooth је Apple-ов фрејмворк за интеракцију са Bluetooth Low Energy на iOS, iPadOS и macOS-у. Фрејмворк пружа комплетан скуп API-ја за рад у оба BLE улога: централни уређај (CBCentralManager) за скенирање и повезивање са периферијом и периферни уређај (CBPeripheralManager) за емулацију BLE сервера. Core Bluetooth апстрахује BLE протокол стек од физичког радија до апликативног GATT профила. Према Apple Developer, 2026, Core Bluetooth је једини званични Apple API за 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 одређује доступне типове писања. Максимална величина једног 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 откривање
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 је једини званични Apple API за 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође