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 мс в зависимости от состояния Bluetooth. Приложение должно дождаться вызова centralManagerDidUpdateState перед началом любых BLE-операций.

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

Состояния CBCentralManager

CBCentralManager проходит через несколько состояний, определяющих, доступен ли BLE-стек для работы. Состояние передаётся через делегат: centralManagerDidUpdateState(_:). Разработчик обязан обработать все состояния — не только poweredOn, но и случаи, когда Bluetooth выключен или недоступен.

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

Unauthorized state становится всё более частым с iOS 13+. Начиная с этой версии, приложение должно иметь разрешение NSBluetoothAlwaysUsageDescription в Info.plist. Без него центральный менеджер переходит в состояние .unauthorized, и сканирование невозможно. Пользователь может изменить разрешение в Settings > Privacy > 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") // Battery Service

        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
// Connect to BLE device
func connectToPeripheral(
    _ peripheral: CBPeripheral
) {
    centralManager.connect(peripheral, options: nil)

    // Set delegate for Peripheral
    peripheral.delegate = self
}

// Delegate: successful connection
func centralManager(
    _ central: CBCentralManager,
    didConnect peripheral: CBPeripheral
) {
    print("Connected to " +
          "\(peripheral.name ?? "unknown")")

    // Start service discovery
    peripheral.discoverServices(nil)
}

// Delegate: connection error
func centralManager(
    _ central: CBCentralManager,
    didFailToConnect peripheral: CBPeripheral,
    error: Error?
) {
    print("Connection failed: 
          \(error?.localizedDescription ?? "")")
}

Таймаут подключения на iOS составляет 30 секунд. Если за это время устройство не ответило на connection request, вызывается 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 поддерживает background execution, но с существенными ограничениями. Для работы в фоне необходимо: включить bluetooth-central в Background Modes в Capabilities проекта, инициализировать CBCentralManager с опцией CBCentralManagerOptionRestoreIdentifierKey для state restoration и обрабатывать события центрального менеджера при переходе в фон.

Ограничения фонового BLE в iOS: scanForPeripherals без фильтрации по UUID не работает в фоне. Приложение должно указывать конкретные UUID сервисов для сканирования. iOS может задерживать delivery BLE-событий на неопределённое время. Core Bluetooth автоматически возобновляет сканирование при обнаружении matching-устройства, даже если приложение в фоне. Timeout на фоновое сканирование: 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
// Handle disconnect with auto-reconnect
func centralManager(
    _ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral,
    error: Error?
) {
    guard let error = error else {
        return // Expected disconnect
    }

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

    // Automatic reconnection
    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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также