CBCentralManager в iOS — какво е това, управление BLE и Core Bluetooth

Автор: IT Sectr Публикувано: 2026-07-16 Време за четене: 11 мин

CBCentralManager — е централният клас на рамката Core Bluetooth в iOS, който управлява сканирането, свързването и взаимодействието с BLE периферни устройства. Core Bluetooth (iOS 5+, 2011) предоставя абстракция на високо ниво над BLE стека на ниво GATT, скривайки от разработчика детайлите на Link Layer и HCI. CBCentralManager изпълнява ролята на Central: сканира етера чрез scanForPeripherals, инициира свързване чрез connect, открива услуги чрез discoverServices и управлява трансфера на данни. Според Apple Developer Documentation (2024), CBCentralManager поддържа до 7 едновременни BLE връзки на устройства с BLE 5.0.

Основни моменти

  • CBCentralManager — iOS клас за управление на BLE сканиране, свързване и трансфер на данни в ролята на Central.
  • Сканирането се стартира чрез scanForPeripherals с филтриране по UUID на услуги за пестене на енергия.
  • Свързването се извършва чрез connect(peripheral:options:) с проследяване на състоянието чрез делегат.
  • iOS поддържа до 7 едновременни BLE връзки на устройства с BLE 5.0.
  • Фоновото сканиране изисква активиране на bluetooth-central в Background Modes и използване на CBCentralManagerScanOptionAllowDuplicatesKey.

Какво е CBCentralManager?

CBCentralManager — е основният клас на Core Bluetooth за имплементиране на ролята Central в BLE архитектурата на iOS. Той управлява целия жизнен цикъл на BLE връзка: от сканиране на рекламиращи устройства до трансфер на данни и прекъсване на връзката. CBCentralManager работи асинхронно чрез делегата CBCentralManagerDelegate, уведомявайки приложението за събития в Bluetooth стека.

Инициализацията на CBCentralManager стартира процеса state restoration: мениджърът проверява състоянието на Bluetooth на устройството и възстановява предишни връзки, ако приложението е било затворено. Процесът на инициализация може да отнеме от 50 до 500 ms в зависимост от състоянието на Bluetooth. Приложението трябва да изчака извикването на centralManagerDidUpdateState преди да започне каквито и да било BLE операции.

Архитектурата на Core Bluetooth е изградена върху модела Delegation: CBCentralManager делегира обработката на събития (откриване на устройства, свързване, грешки) на протокола CBCentralManagerDelegate. За работа с конкретен Peripheral се използва протоколът CBPeripheralDelegate, който уведомява за откриване на услуги, характеристики и получаване на данни. Този асинхронен модел осигурява неблокираща работа на UI.

Състояния на CBCentralManager

CBCentralManager преминава през няколко състояния, които определят дали BLE стекът е достъпен за работа. Състоянието се предава чрез делегата: centralManagerDidUpdateState(_:). Разработчикът трябва да обработва всички състояния — не само poweredOn, но и случаите, когато Bluetooth е изключен или недостъпен.

СъстояниеЗначениеДействие на разработчика
.poweredOnBluetooth е включен и готовЗапочнете сканиране
.poweredOffBluetooth е изключенПокажете предупреждение на потребителя
.unauthorizedНяма разрешениеПоискайте разрешение в Настройки
.unsupportedУстройството не поддържа BLEСкрийте BLE функциите
.unknownСъстоянието не е определеноИзчакайте следващата актуализация
.resettingBluetooth се рестартираИзчакайте възстановяване

Unauthorized state става все по-често срещано от iOS 13+. От тази версия нататък приложението трябва да има разрешение NSBluetoothAlwaysUsageDescription в Info.plist. Без него централният мениджър преминава в състояние .unauthorized и сканирането е невъзможно. Потребителят може да промени разрешението по всяко време в Настройки > Поверителност > Bluetooth.

Сканиране на BLE устройства

scanForPeripherals(withServices:options:) — основният метод за стартиране на сканиране. Параметърът withServices приема масив от UUID на услуги за филтриране: ако се подаде nil, ще бъдат открити всички устройства, което значително увеличава консумацията на енергия. Препоръчително е винаги да филтрирате по UUID на услугите, от които приложението се нуждае. Опциите за сканиране включват CBCentralManagerScanOptionAllowDuplicatesKey (повтарящи се уведомления за едно и също устройство).

swift
import CoreBluetooth

class BLEController: NSObject,
    CBCentralManagerDelegate {

    private var centralManager: CBCentralManager!

    override init() {
        super.init()
        centralManager =
            CBCentralManager(
                delegate: self,
                queue: nil
            )
    }

    func startScanning() {
        let serviceUUID =
            CBUUID("180F") // Услуга на батерията

        centralManager.scanForPeripherals(
            withServices: [serviceUUID],
            options: [
                CBCentralManagerScanOptionAllowDuplicatesKey: false
            ]
        )
    }
}

При откриване на устройство се извиква centralManager(_:didDiscover:advertisementData:rssi:). Параметърът advertisementData съдържа пълен речник на данните на рекламния пакет, включително името на устройството (CBAdvertisementDataLocalNameKey), UUID на услугите (CBAdvertisementDataServiceUUIDsKey) и данни на производителя (CBAdvertisementDataManufacturerDataKey). RSSI — ниво на сигнала в dBm, достъпно в момента на откриване.

Свързване с Peripheral

connect(_:options:) — метод за установяване на BLE връзка с открит Peripheral. След извикването на connect, iOS се опитва да се свърже с устройството. Успешното свързване се потвърждава от centralManager(_:didConnect:), грешка от centralManager(_:didFailToConnect:error:). Опциите за свързване включват CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey и CBConnectPeripheralOptionNotifyOnNotificationKey за фонови уведомления.

swift
// Свържете се с BLE устройство
func connectToPeripheral(
    _ peripheral: CBPeripheral
) {
    centralManager.connect(peripheral, options: nil)

    // Задайте делегат за Peripheral
    peripheral.delegate = self
}

// Делегат: успешна връзка
func centralManager(
    _ central: CBCentralManager,
    didConnect peripheral: CBPeripheral
) {
    print("Свързан към " +
          "\(peripheral.name ?? "unknown")")

    // Стартирайте откриване на услуги
    peripheral.discoverServices(nil)
}

// Делегат: грешка при свързване
func centralManager(
    _ central: CBCentralManager,
    didFailToConnect peripheral: CBPeripheral,
    error: Error?
) {
    print("Connection failed: 
          \(error?.localizedDescription ?? "")")
}

Таймаут на свързване в iOS е 30 секунди. Ако устройството не отговори на заявката за свързване в този период, се извиква didFailToConnect. Фактори, влияещи на таймаута: разстояние до устройството, смущения, дали устройството в момента рекламира. Преди свързване се уверете, че устройството е в режим connectable advertising (ADV_IND, а не ADV_NONCONN_IND).

Откриване на услуги и характеристики

След свързване трябва да се открият услугите (discoverServices) и характеристиките (discoverCharacteristics) на Peripheral. Това е задължителна стъпка преди четене или запис на данни. Процесът е асинхронен: discoverServices връща резултат чрез peripheral(_:didDiscoverServices:), а discoverCharacteristics чрез peripheral(_:didDiscoverCharacteristicsFor:error:).

Препоръчително е да предавате на discoverServices масив от интересуващи ви UUID, а не nil. Филтрирането ускорява откриването и пести енергия. Ако услугата не бъде намерена, iOS ще съобщи празен масив. След откриване на характеристиките можете да четете техните стойности (readValue), да се абонирате за уведомления (setNotifyValue) или да записвате данни (writeValue).

Важен детайл: MTU се договаря автоматично след свързване. За да получите текущото MTU, използвайте peripheral.maximumWriteValueLength(for: .withResponse) или .withoutResponse. В iOS максималният MTU е 512 байта за BLE 5.0 устройства. Ако трябва да прехвърлите данни, по-големи от MTU, имплементирайте фрагментация на ниво приложение.

Фоново сканиране и ограничения на iOS

Фоново сканиране на BLE устройства в iOS изисква специална конфигурация. Core Bluetooth поддържа фонова изпълнение, но със значителни ограничения. За работа във фонов режим е необходимо: активирайте bluetooth-central в Background Modes в Capabilities на проекта, инициализирайте CBCentralManager с опция CBCentralManagerOptionRestoreIdentifierKey за state restoration и обработвайте събитията на централния мениджър при преминаване във фонов режим.

BLE ограничения във фонов режим в iOS: scanForPeripherals без филтриране по UUID не работи във фонов режим. Приложението трябва да посочи конкретни UUID на услуги за сканиране. iOS може да забави доставянето на BLE събития за неопределено време. Core Bluetooth автоматично подновява сканирането при откриване на съвпадащо устройство, дори ако приложението е на заден план. Таймаут на фоново сканиране: iOS може да спре сканирането след 10–30 минути за пестене на енергия.

State Restoration — механизмът на Core Bluetooth, който позволява възстановяване на BLE връзки след рестартиране на приложението или рестарт на iOS. За използване: посочете CBCentralManagerOptionRestoreIdentifierKey при инициализация, имплементирайте centralManager(_:willRestoreState:) в делегата и възстановете списъка на свързаните Peripheral от подадения речник. State Restoration е критична функционалност за BLE приложения, работещи във фонов режим, като фитнес тракери или медицински устройства.

Обработка на грешки и възстановяване на връзка

CBCentralManager генерира грешки в няколко сценария: свързването неуспешно (didFailToConnect), връзката е прекъсната (didDisconnectPeripheral), характеристиката не е достъпна за четене/запис (didWriteValue error). Всички Core Bluetooth грешки се връщат чрез обекта Error с домейн CBErrorDomain. Най-честите кодове: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A).

Стратегия за възстановяване на връзка: при получаване на didDisconnectPeripheral проверете кода на грешката. Ако грешката е CBErrorConnectionTimeout или CBErrorPeripheralDisconnected — планирайте автоматично повторно свързване след 1–5 секунди. Ако грешката е CBErrorOperationNotSupported — запишете в лог и не се опитвайте да повторите операцията. За критични връзки (медицински устройства) използвайте exponential backoff с максимален интервал от 60 секунди.

swift
// Обработка на прекъсване с автоматично повторно свързване
func centralManager(
    _ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral,
    error: Error?
) {
    guard let error = error else {
        return // Очаквано прекъсване
    }

    print("Disconnected: \(error.localizedDescription)")

    // Автоматично повторно свързване
    if shouldAutoReconnect {
        DispatchQueue.main.asyncAfter(
            deadline: .now() + reconnectDelay
        ) {
            central.connect(peripheral)
        }
    }
}

При разработка на надеждно BLE приложение на iOS вземете предвид: Core Bluetooth не гарантира доставката на всички пакети при слаб сигнал. За надежден трансфер използвайте writeType .withResponse (потвърден запис) и се абонирайте за уведомления (setNotifyValue) за получаване на данни от Peripheral. Водете лог на грешките за диагностициране на проблеми с връзката в производствена среда.

Често задавани въпроси

Защо CBCentralManager не открива устройства?

Проверете състоянието на мениджъра чрез centralManagerDidUpdateState. Уверете се, че разрешението NSBluetoothAlwaysUsageDescription присъства в Info.plist, Bluetooth е включен на устройството и периферното устройство рекламира с правилния тип (connectable advertising, а не non-connectable).

Колко BLE устройства могат едновременно да се свържат с iOS?

На устройства с BLE 5.0 (iPhone 8 и по-нови) — до 7 едновременни връзки. На по-стари устройства — до 3–5. Броят на сканираните устройства е неограничен, но активните връзки имат строг лимит, зададен от Bluetooth Controller.

Колко често мога да сканирам BLE на iOS без загуба на батерия?

Препоръчително е да сканирате с филтър по UUID и да изключвате сканирането, когато устройството бъде намерено. Непрекъснатото сканиране разрежда батерията: 1 час непрекъснато сканиране консумира ~10–15% от батерията на iPhone. Използвайте таймери и условия за спиране на сканирането.

Каква е разликата между CBCentralManager и CBPeripheralManager?

CBCentralManager — за сканиране и свързване с външни BLE устройства (роля Central). CBPeripheralManager — вашето iOS устройство само да действа като BLE периферия (да рекламира услуги). Един екземпляр може да бъде само в една роля.

Как да обработя загуба на връзка с BLE устройство?

Имплементирайте centralManager(_:didDisconnectPeripheral:error:). Ако грешката не е nil — планирайте автоматично повторно свързване с exponential backoff (1 с → 2 с → 4 с → 8 с → макс 60 с). Ако грешката е nil — устройството се е изключило нормално (например потребителят е натиснал бутон на устройството).

Резюме

  • CBCentralManager — основният клас на Core Bluetooth за управление на BLE сканиране, свързване и трансфер на данни в ролята Central на iOS.
  • Сканирането се стартира чрез scanForPeripherals с опционално филтриране по UUID на услуги за намаляване на консумацията на енергия.
  • Свързването се извършва чрез connect, успехът се потвърждава от didConnect, грешката от didFailToConnect с таймаут от 30 секунди.
  • След свързване трябва да бъдат открити услугите и характеристиките чрез discoverServices и discoverCharacteristics.
  • Фоновото сканиране изисква bluetooth-central Background Mode и се поддържа с ограничения (филтриране по UUID, възможни закъснения).
  • iOS поддържа до 7 едновременни BLE връзки на устройства с BLE 5.0, state restoration за възстановяване след рестарт.
  • Обработка на грешки и автоматично повторно свързване с exponential backoff — основата на надеждно BLE приложение на iOS.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също