CBCentralManager é a classe central do framework Core Bluetooth no iOS que gerencia a varredura, conexão e interação com dispositivos periféricos BLE. O Core Bluetooth (iOS 5+, 2011) fornece uma abstração de alto nível sobre a pilha BLE no nível GATT, ocultando do desenvolvedor os detalhes da Link Layer e HCI. O CBCentralManager implementa o papel Central: ele varre o ar via scanForPeripherals, inicia a conexão via connect, descobre serviços via discoverServices e gerencia a transferência de dados. De acordo com a Documentação do Desenvolvedor Apple (2024), o CBCentralManager suporta até 7 conexões simultâneas a dispositivos BLE em dispositivos com BLE 5.0.
Pontos Principais
CBCentralManager é a classe principal do Core Bluetooth para implementar o papel Central na arquitetura BLE no iOS. Ele gerencia todo o ciclo de vida da conexão BLE: desde a varredura de dispositivos em propaganda até a transferência de dados e desconexão. O CBCentralManager funciona de forma assíncrona através do delegado CBCentralManagerDelegate, notificando o aplicativo sobre eventos na pilha Bluetooth.
A inicialização do CBCentralManager inicia o processo de restauração de estado: o gerenciador verifica o estado do Bluetooth no dispositivo e restaura conexões anteriores se o aplicativo foi fechado. O processo de inicialização pode levar de 50 a 500 ms dependendo do estado do Bluetooth. O aplicativo deve aguardar a chamada centralManagerDidUpdateState antes de iniciar qualquer operação BLE.
A arquitetura do Core Bluetooth é construída no padrão de Delegação: o CBCentralManager delega o tratamento de eventos (descoberta de dispositivos, conexão, erros) ao protocolo CBCentralManagerDelegate. Para trabalhar com um Periférico específico, é usado o protocolo CBPeripheralDelegate, que notifica sobre serviços descobertos, características e dados recebidos. Este modelo assíncrono garante uma interface de usuário sem bloqueios.
CBCentralManager passa por vários estados que determinam se a pilha BLE está disponível. O estado é transmitido através do delegado: centralManagerDidUpdateState(_:). O desenvolvedor deve tratar todos os estados — não apenas poweredOn, mas também os casos em que o Bluetooth está desligado ou indisponível.
| Estado | Valor | Ação do Desenvolvedor |
|---|---|---|
| .poweredOn | Bluetooth está ligado e pronto | Iniciar varredura |
| .poweredOff | Bluetooth está desligado | Mostrar alerta ao usuário |
| .unauthorized | Sem permissão | Solicitar permissão em Ajustes |
| .unsupported | Dispositivo não suporta BLE | Ocultar funções BLE |
| .unknown | Estado não definido | Aguardar próxima atualização |
| .resetting | Bluetooth está reiniciando | Aguardar recuperação |
Estado não autorizado está se tornando mais comum desde o iOS 13+. A partir desta versão, o aplicativo deve ter a permissão NSBluetoothAlwaysUsageDescription no Info.plist. Sem ela, o gerenciador central transita para o estado .unauthorized, e a varredura é impossível. O usuário pode alterar a permissão em Ajustes > Privacidade > Bluetooth a qualquer momento.
scanForPeripherals(withServices:options:) é o método principal para iniciar a varredura. O parâmetro withServices aceita um array de UUIDs de serviço para filtrar: se nil for passado, todos os dispositivos serão descobertos, o que aumenta significativamente o consumo de energia. Recomenda-se sempre filtrar pelos UUIDs de serviço necessários ao aplicativo. As opções de varredura incluem CBCentralManagerScanOptionAllowDuplicatesKey (notificações repetidas sobre o mesmo dispositivo).
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") // Serviço de Bateria
centralManager.scanForPeripherals(
withServices: [serviceUUID],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
}
Quando um dispositivo é descoberto, centralManager(_:didDiscover:advertisementData:rssi:) é chamado. O parâmetro advertisementData contém o dicionário completo dos dados do pacote de propaganda, incluindo o nome do dispositivo (CBAdvertisementDataLocalNameKey), UUIDs de serviço (CBAdvertisementDataServiceUUIDsKey) e dados do fabricante (CBAdvertisementDataManufacturerDataKey). RSSI é o nível de sinal em dBm disponível no momento da descoberta.
connect(_:options:) é o método para estabelecer uma conexão BLE com um Periférico descoberto. Após chamar connect, o iOS tenta conectar ao dispositivo. Uma conexão bem-sucedida é confirmada via centralManager(_:didConnect:), um erro — via centralManager(_:didFailToConnect:error:). As opções de conexão incluem CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey e CBConnectPeripheralOptionNotifyOnNotificationKey para notificações em segundo plano.
// Conectar ao dispositivo BLE
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// Definir delegado para Periférico
peripheral.delegate = self
}
// Delegado: conexão bem-sucedida
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
print("Conectado a " +
"\(peripheral.name ?? "unknown")")
// Iniciar descoberta de serviços
peripheral.discoverServices(nil)
}
// Delegado: erro de conexão
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
print("Connection failed:
\(error?.localizedDescription ?? "")")
}
O tempo limite de conexão no iOS é de 30 segundos. Se o dispositivo não respondeu à solicitação de conexão dentro deste tempo, didFailToConnect é chamado. O tempo limite é afetado por: distância do dispositivo, interferência e se o dispositivo está atualmente em propaganda. Antes de conectar, certifique-se de que o dispositivo está no modo de propaganda conectável (ADV_IND, não ADV_NONCONN_IND).
Após a conexão, você deve descobrir os serviços (discoverServices) e características (discoverCharacteristics) do Periférico. Este é um passo obrigatório antes de ler ou escrever dados. O processo é assíncrono: discoverServices retorna resultados via peripheral(_:didDiscoverServices:), e discoverCharacteristics — via peripheral(_:didDiscoverCharacteristicsFor:error:).
Recomenda-se passar um array de UUIDs relevantes para discoverServices em vez de nil. A filtragem acelera a descoberta e economiza energia. Se um serviço não for encontrado, o iOS reportará um array vazio. Após descobrir as características, você pode ler seus valores (readValue), inscrever-se em notificações (setNotifyValue) ou escrever dados (writeValue).
Uma nuance importante: o MTU é negociado automaticamente após a conexão. Para obter o MTU atual, use peripheral.maximumWriteValueLength(for: .withResponse) ou .withoutResponse. No iOS, o MTU máximo é de 512 bytes para dispositivos BLE 5.0. Se precisar transferir dados maiores que o MTU, implemente fragmentação no nível do aplicativo.
A varredura em segundo plano de dispositivos BLE no iOS requer configuração especial. O Core Bluetooth suporta execução em segundo plano, mas com limitações significativas. Para trabalhar em segundo plano, você precisa: ativar bluetooth-central em Background Modes nas Capacidades do projeto, inicializar o CBCentralManager com a opção CBCentralManagerOptionRestoreIdentifierKey para restauração de estado e tratar os eventos do gerenciador central ao entrar em segundo plano.
Limitações do BLE em segundo plano no iOS: scanForPeripherals sem filtragem por UUID não funciona em segundo plano. O aplicativo deve especificar UUIDs de serviço concretos para varredura. O iOS pode atrasar a entrega de eventos BLE indefinidamente. O Core Bluetooth retoma automaticamente a varredura quando um dispositivo correspondente é descoberto, mesmo se o aplicativo estiver em segundo plano. Tempo limite para varredura em segundo plano: o iOS pode parar a varredura após 10–30 minutos para economizar energia.
Restauração de Estado é um mecanismo do Core Bluetooth que permite restaurar conexões BLE após uma reinicialização do aplicativo ou reinício do iOS. Para usá-lo: especifique CBCentralManagerOptionRestoreIdentifierKey durante a inicialização, implemente centralManager(_:willRestoreState:) no delegado e restaure a lista de Periféricos conectados do dicionário passado. A Restauração de Estado é uma funcionalidade crítica para aplicativos BLE que funcionam em segundo plano, como rastreadores de fitness ou dispositivos médicos.
CBCentralManager gera erros em vários cenários: conexão falhou (didFailToConnect), conexão perdida (didDisconnectPeripheral), característica não disponível para leitura/escrita (erro didWriteValue). Todos os erros do Core Bluetooth são retornados através do objeto Error com domínio CBErrorDomain. Os códigos mais comuns: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A).
Estratégia de recuperação de conexão: ao receber didDisconnectPeripheral, verifique o código de erro. Se o erro for CBErrorConnectionTimeout ou CBErrorPeripheralDisconnected — agende uma reconexão automática em 1–5 segundos. Se o erro for CBErrorOperationNotSupported — registre e não tente repetir a operação. Para conexões críticas (dispositivos médicos), use backoff exponencial com intervalo máximo de 60 segundos.
// Lidar com desconexão com reconexão automática
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
guard let error = error else {
return // Desconexão esperada
}
print("Disconnected: \(error.localizedDescription)")
// Reconexão automática
if shouldAutoReconnect {
DispatchQueue.main.asyncAfter(
deadline: .now() + reconnectDelay
) {
central.connect(peripheral)
}
}
}
Ao desenvolver um aplicativo BLE robusto no iOS, lembre-se: o Core Bluetooth não garante a entrega de todos os pacotes com sinal fraco. Para transmissão confiável, use writeType .withResponse (escrita confirmada) e inscreva-se em notificações (setNotifyValue) para receber dados do Periférico. Mantenha um registro de erros para diagnosticar problemas de conexão em produção.
Perguntas Frequentes
Verifique o estado do gerenciador via centralManagerDidUpdateState. Certifique-se de que a permissão NSBluetoothAlwaysUsageDescription está no Info.plist, o Bluetooth está ativado no dispositivo e o periférico está em propaganda com o tipo correto (propaganda conectável, não não-conectável).
Em dispositivos com BLE 5.0 (iPhone 8 e mais recentes) — até 7 conexões simultâneas. Em dispositivos mais antigos — até 3–5. O número de dispositivos varridos é ilimitado, mas as conexões ativas têm um limite rígido estabelecido pelo Controlador Bluetooth.
Recomenda-se varrer com filtragem por UUID e parar a varredura quando o dispositivo for encontrado. A varredura contínua drena a bateria: 1 hora de varredura ininterrupta consome ~10–15% da carga do iPhone. Use temporizadores e condições para parar a varredura.
CBCentralManager é para varrer e conectar a dispositivos BLE externos (papel Central). CBPeripheralManager é para seu dispositivo iOS atuar como periférico BLE (propagar serviços). Uma instância só pode estar em um papel.
Implemente centralManager(_:didDisconnectPeripheral:error:). Se o erro não for nil — agende uma reconexão automática com backoff exponencial (1 s → 2 s → 4 s → 8 s → máx 60 s). Se o erro for nil — o dispositivo desconectou normalmente (por exemplo, o usuário pressionou um botão no dispositivo).
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também