Core Bluetooth este frameworkul Apple pentru interacțiunea cu Bluetooth Low Energy pe iOS, iPadOS și macOS. Frameworkul oferă un set complet de API-uri pentru lucrul în ambele roluri BLE: dispozitiv central (CBCentralManager) pentru scanare și conectare la periferice și dispozitiv periferic (CBPeripheralManager) pentru emularea unui server BLE. Core Bluetooth abstractizează stiva de protocol BLE de la radioul fizic până la profilul GATT aplicativ. Conform Apple Developer, 2026, Core Bluetooth este singurul API oficial Apple pentru dezvoltare BLE, suportând BLE 4.0–5.4 cu extended advertising, 2M PHY și LE Audio.
Principalele Puncte
Core Bluetooth împarte stiva BLE în două roluri logice definite de specificația Bluetooth SIG. Rolul dispozitivului central (Central) este reprezentat de clasa CBCentralManager — inițiază scanarea, stabilește conexiuni și gestionează lista de CBPeripheral conectate. Rolul dispozitivului periferic (Peripheral) este reprezentat de CBPeripheralManager — publică servicii și caracteristici, răspunde la cererile centralei și trimite notificări. O sesiune iOS poate funcționa simultan în ambele roluri pe diferite radiouri BLE, dar aplicația tipică folosește un singur rol.
Arhitectura Core Bluetooth include cinci abstracții cheie. CBCentralManager gestionează starea adaptorului Bluetooth al dispozitivului: poweredOn (gata de lucru), poweredOff (Bluetooth dezactivat), unauthorized (fără permisiune), unsupported (BLE indisponibil). CBPeripheral reprezintă un dispozitiv BLE la distanță cu UUID-ul, numele, RSSI-ul și ierarhia GATT. CBService — un grup logic de caracteristici. CBCharacteristic — un punct de date pentru citire/scriere/notificări. CBPeripheralManager creează un server GATT local pentru emularea perifericului.
| Clasă | Rol | Metode principale |
|---|---|---|
| CBCentralManager | Dispozitiv central | scanForPeripherals, connect, cancelPeripheralConnection, retrievePeripherals |
| CBPeripheral | Periferic la distanță | discoverServices, discoverCharacteristics, readValue, writeValue, setNotifyValue |
| CBPeripheralManager | Periferic local | addService, removeService, startAdvertising, respondToRequest, updateValue |
| CBCentral | Centrală la distanță | maximumUpdateValueLength, identifier, ancsAuthorized |
Stările CBCentralManager gestionează toate operațiunile BLE. La pornirea aplicației, centralManagerDidUpdateState este apelată cu starea curentă a Bluetooth. Dacă starea nu este .poweredOn, orice apeluri BLE sunt ignorate de sistem. Dezvoltatorul trebuie să verifice state înainte de fiecare scanare și conectare. Tranziția de la .poweredOff la .poweredOn are loc când Bluetooth este activat în Setările iOS — delegatul primește o reapelare și aplicația poate relua scanarea.
CBCentralManager — punctul de intrare pentru toate operațiunile BLE din partea dispozitivului central. Inițializarea primește un delegat (CBCentralManagerDelegate) și o coadă DispatchQueue — recomandarea Apple este să folosiți main queue pentru simplitate sau serial queue pentru performanță. După inițializare, frameworkul verifică automat starea Bluetooth și apelează centralManagerDidUpdateState: — primul delegat obligatoriu de procesat.
Scanarea este pornită prin metoda scanForPeripheralsWithServices:options:. Primul parametru este un array de CBUUID ale serviciilor pentru filtrare: dacă UUID-urile serviciilor de interes sunt cunoscute, transmiterea lor reduce consumul de energie și timpul de căutare. Dacă este nil, toate dispozitivele BLE din rază sunt detectate. Opțiunile includ .allowDuplicatesKey (redetectarea aceluiași dispozitiv) și .solicitedServiceUUIDsKey (pentru servicii publicate pe centrală).
import CoreBluetooth
class BLECentral: NSObject {
private var centralManager: CBCentralManager!
private var discoveredPeripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: .main)
}
// Porniți scanarea BLE
func startScan() {
guard centralManager.state == .poweredOn else {
print("Bluetooth indisponibil")
return
}
// Scanați toate dispozitivele (nil = fără filtru)
centralManager.scanForPeripherals(withServices: nil,
options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
}
// Opriți scanarea
func stopScan() {
centralManager.stopScan()
}
// Conectați-vă la dispozitivul selectat
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)")
}
}
Clasa BLECentral demonstrează ciclul complet de scanare și conectare a dispozitivelor BLE. centralManagerDidUpdateState pornește scanarea când Bluetooth este activat. didDiscoverPeripheral colectează dispozitivele găsite în array-ul discoveredPeripherals cu deduplicare după identifier. După conectare (didConnect), descoperirea serviciilor este pornită imediat — acesta este un pas obligatoriu înainte de orice operațiuni GATT.
CBPeripheralManager — clasă pentru emularea unui dispozitiv periferic BLE pe iOS. Aplicația în rolul de periferic poate publica propriile servicii și caracteristici, primi cereri de citire/scriere de la dispozitivul central și trimite notificări. CBPeripheralManager este folosit pentru accesoriile BLE emulate de iPhone: telecomenzi, tastaturi, trackere, gateway-uri IoT.
Ciclul de viață al CBPeripheralManager începe cu inițializarea și delegatul CBPeripheralManagerDelegate. După confirmarea poweredOn prin peripheralManagerDidUpdateState:, serviciile sunt publicate (addService:) și publicitatea este pornită (startAdvertising:). Datele de publicitate CBAdvertisementData includ numele local (CBAdvertisementDataLocalNameKey), UUID-urile serviciilor (CBAdvertisementDataServiceUUIDsKey) și nivelul de putere (CBAdvertisementDataTxPowerLevelKey). Dimensiunea maximă a pachetului de publicitate este de 31 de octeți pentru BLE 4.0, 251 de octeți pentru extended advertising BLE 5.0+.
// Periferic BLE pe iOS prin 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)
}
// Publicați serviciul cu caracteristică
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)
}
// Porniți publicitatea
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()
}
}
// Procesați cererea de citire
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveRead request: CBATTRequest) {
let data = "CurrentValue".data(using: .utf8)!
request.value = data
peripheralManager.respond(to: request, withResult: .success)
}
// Procesați cererea de scriere
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)
}
}
Clasa BLEPeripheral creează un server BLE cu o caracteristică care suportă citire, scriere și notificări. După inițializare, peripheralManagerDidUpdateState publică serviciul prin addService:, apoi pornește publicitatea prin startAdvertising:. Gestionarii didReceiveRead și didReceiveWrite răspund la cererile GATT primite de la dispozitivul central. Pentru trimiterea notificărilor se folosește metoda updateValue:forCharacteristic:onSubscribedCentrals:.
Operațiunile GATT (Generic Attribute Profile) stau la baza schimbului de date în Core Bluetooth. După descoperirea serviciilor și caracteristicilor, dispozitivul central poate efectua trei tipuri de operațiuni: citirea valorii unei caracteristici, scrierea valorii și abonarea la notificări/indicații. Fiecare operațiune este asincronă și returnează rezultatul prin delegatul CBPeripheralDelegate corespunzător.
Citirea se realizează prin apelul readValueForCharacteristic:. Valoarea sosește în peripheral:didUpdateValueForCharacteristic:error:. Important: citirea returnează valoarea curentă de pe dispozitiv, nu una stocată în cache. Dacă dispozitivul nu suportă citirea (proprietatea .read), apelul va returna o eroare. Pentru valori mari (mai mari decât MTU), BLE fragmentează și asamblează automat datele la nivelul GATT.
Scrierea se realizează prin writeValue:forCharacteristic:type:. BLE suportă două modele de scriere: withResponse (fiabil, cu confirmare) și withoutResponse (rapid, fără confirmare). Proprietatea CBCharacteristic.properties determină tipurile de scriere disponibile. Dimensiunea maximă a unui singur pachet de scriere este limitată de MTU: 23 de octeți pentru BLE 4.0 (20 de octeți date utile + 3 octeți antet), până la 247 de octeți pentru BLE 5.0 cu extended MTU (MTU 251).
Notificările sunt activate prin apelul setNotifyValue:true forCharacteristic:. După abonare, perifericul trimite automat actualizări prin peripheral:didUpdateValueForCharacteristic: de fiecare dată când valoarea caracteristicii se schimbă. Pentru dezactivarea notificărilor se apelează setNotifyValue:false forCharacteristic:. Core Bluetooth gestionează automat descriptorul CCCD pe periferic.
| Operațiune | Metodă | Delegat | Tip de transmisie |
|---|---|---|---|
| Citire | readValueForCharacteristic: | didUpdateValueForCharacteristic | Polling (cerere-răspuns) |
| Scriere withResponse | writeValue:forCharacteristic:type:withResponse | didWriteValueForCharacteristic | Cu confirmare |
| Scriere withoutResponse | writeValue:forCharacteristic:type:withoutResponse | Fără delegat | Fără confirmare |
| Notificare | setNotifyValue:true forCharacteristic: | didUpdateNotificationStateForCharacteristic + didUpdateValueForCharacteristic | Push de la periferic |
Modul de fundal Core Bluetooth permite aplicației BLE să continue scanarea, să mențină conexiunile și să primească notificări în timp ce se află în fundal. Pentru activare este necesar: activați capability „Uses Bluetooth LE accessories” în Xcode (Info.plist → Required background modes → App communicates using Core Bluetooth) și adăugați cheia „bluetooth-central” în UIBackgroundModes. Pentru rolul periferic — „bluetooth-peripheral”.
State Restoration — mecanismul Core Bluetooth pentru restaurarea stării conexiunilor BLE după repornirea aplicației de către sistemul iOS. La activarea modului de fundal și specificarea restoreIdentifier în inițializarea CBCentralManager sau CBPeripheralManager, iOS salvează starea stivei BLE la terminarea aplicației și o restaurează la următoarea pornire. Delegatul centralManager:willRestoreState: primește un dicționar cu CBPeripheral salvate și conexiuni în așteptare.
// Configurarea Core Bluetooth cu 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 {
// Restaurați starea după repornire
func centralManager(_ central: CBCentralManager,
willRestoreState dict: [String : Any]) {
if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
as? [CBPeripheral] {
for peripheral in peripherals {
peripheral.delegate = self
// Restaurați descoperirea GATT
peripheral.discoverServices(nil)
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("Bluetooth gata după restaurare")
}
}
}
În configurația BLECentralWithRestoration, cheia CBCentralManagerOptionRestoreIdentifierKey activează salvarea stării. Dacă aplicația a fost terminată de iOS (de exemplu, din cauza lipsei de memorie), la următoarea pornire centralManager:willRestoreState: primește lista CBPeripheral conectate anterior. Aplicația restaurează delegații și efectuează rediscovery al serviciilor — utilizatorul nu observă întreruperea conexiunii. Fără State Restoration, toate sesiunile BLE se pierd la terminarea aplicației.
Exemplul complet al unei aplicații BLE în Swift combină dispozitivul central și periferic într-un singur proiect. Aplicația poate funcționa în două moduri: detectează și se conectează la dispozitive BLE (Central) sau emulează un accesoriu BLE (Peripheral). Mai jos este prezentată arhitectura cu un manager BLE comun care alege rolul la pornire.
// Manager BLE universal pentru centrală și periferic
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)
}
}
// Dispozitiv central: scanare
func scanForDevices() {
centralManager?.scanForPeripherals(withServices: nil, options: nil)
}
// Dispozitiv periferic: publicitate
func advertiseService() {
let data: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [advertisedServiceUUID]
]
peripheralManager?.startAdvertising(data)
}
}
// Utilizare la pornire
let isCentral = UserDefaults.standard.bool(forKey: "isCentral")
let manager = BLEManager(role: isCentral ? .central : .peripheral)
if isCentral {
manager.scanForDevices()
} else {
manager.advertiseService()
}
Managerul BLEManager alege rolul la inițializare și creează Managerul corespunzător (CBCentralManager sau CBPeripheralManager). Indicatorul rolului poate fi stocat în UserDefaults sau transmis printr-un server de configurare. Această abordare permite aplicației BLE să se adapteze la scenariul de utilizare: la punctul de vânzare, iPhone-ul funcționează ca centrală pentru scanarea terminalelor de plată, pe gateway-ul IoT — ca periferic pentru colectarea datelor de la senzori.
Întrebări frecvente
Core Bluetooth — frameworkul Apple pentru dezvoltare BLE pe iOS, iPadOS și macOS. Oferă API-uri pentru funcționarea dispozitivului central (CBCentralManager) și periferic (CBPeripheralManager). Suportă BLE 4.0–5.4, extended advertising, 2M PHY și LE Audio. Core Bluetooth este singurul API oficial Apple pentru comunicare BLE, obligatoriu pentru toate aplicațiile iOS care lucrează cu Bluetooth Low Energy.
CBCentralManager — clasă pentru lucrul în rolul de dispozitiv central: scanează perifericele BLE, stabilește conexiuni, citește și scrie caracteristici. CBPeripheralManager — clasă pentru lucrul în rolul de periferic: publică servicii, răspunde la cererile de citire/scriere și trimite notificări. Un iPhone poate funcționa simultan în două roluri prin diferite instanțe ale managerilor.
Pentru lucrul BLE în fundal, activați capability „Uses Bluetooth LE accessories” în Xcode și adăugați cheia „bluetooth-central” în UIBackgroundModes. Pentru rolul periferic — „bluetooth-peripheral”. Specificați restoreIdentifier la inițializarea managerului pentru State Restoration. Fără aceste setări, aplicația în fundal nu primește evenimente BLE și pierde conexiunile.
Cauze principale: CBCentralManager.state != .poweredOn (Bluetooth dezactivat sau neautorizat), delegatul nu este setat, dispozitivul este în afara razei sau nu trimite pachete de publicitate. Verificați permisiunea NSBluetoothAlwaysUsageDescription în Info.plist, starea Bluetooth în centralManagerDidUpdateState și asigurați-vă că scanForPeripherals este apelată doar la .poweredOn.
Da, Core Bluetooth suportă conectarea simultană la mai multe dispozitive BLE. Fiecare CBPeripheral este gestionat independent prin propriul delegat. iOS limitează numărul de conexiuni BLE simultane la nivel de sistem (de obicei 5–7 pentru iPhone). Pentru scenarii 1:N (de exemplu, un centru de fitness cu 10 trackere), este necesară punerea în coadă și deservirea ciclică a perifericelor.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și