CBCentralManager in iOS — cos'è, gestione BLE e Core Bluetooth

Autore: IT Sectr Pubblicato: 2026-07-16 Tempo di lettura: 11 min

CBCentralManager è la classe centrale del framework Core Bluetooth in iOS che gestisce la scansione, la connessione e l'interazione con i dispositivi periferici BLE. Core Bluetooth (iOS 5+, 2011) fornisce un'astrazione di alto livello sullo stack BLE a livello GATT, nascondendo allo sviluppatore i dettagli di Link Layer e HCI. CBCentralManager implementa il ruolo Central: scansiona l'etere tramite scanForPeripherals, avvia la connessione tramite connect, scopre i servizi tramite discoverServices e gestisce il trasferimento dati. Secondo la Documentazione Sviluppatori Apple (2024), CBCentralManager supporta fino a 7 connessioni simultanee a dispositivi BLE su dispositivi con BLE 5.0.

Punti Chiave

  • CBCentralManager è la classe iOS per gestire la scansione BLE, le connessioni e il trasferimento dati nel ruolo Central.
  • La scansione viene avviata tramite scanForPeripherals con filtraggio per UUID del servizio per risparmiare energia.
  • La connessione viene eseguita tramite connect(peripheral:options:) con monitoraggio dello stato attraverso il delegato.
  • iOS supporta fino a 7 connessioni BLE simultanee su dispositivi con BLE 5.0.
  • La scansione in background richiede l'attivazione di bluetooth-central in Background Modes e l'uso di CBCentralManagerScanOptionAllowDuplicatesKey.

Cos'è CBCentralManager?

CBCentralManager è la classe principale di Core Bluetooth per implementare il ruolo Central nell'architettura BLE su iOS. Gestisce l'intero ciclo di vita della connessione BLE: dalla scansione dei dispositivi in pubblicità al trasferimento dati e alla disconnessione. CBCentralManager funziona in modo asincrono tramite il delegato CBCentralManagerDelegate, notificando all'app gli eventi nello stack Bluetooth.

L'inizializzazione di CBCentralManager avvia il processo di state restoration: il manager verifica lo stato del Bluetooth sul dispositivo e ripristina le connessioni precedenti se l'app è stata chiusa. Il processo di inizializzazione può richiedere da 50 a 500 ms a seconda dello stato del Bluetooth. L'app deve attendere la chiamata centralManagerDidUpdateState prima di iniziare qualsiasi operazione BLE.

L'architettura di Core Bluetooth si basa sul pattern di Delegation: CBCentralManager delega la gestione degli eventi (scoperta dispositivi, connessione, errori) al protocollo CBCentralManagerDelegate. Per lavorare con una periferica specifica, viene utilizzato il protocollo CBPeripheralDelegate, che notifica la scoperta di servizi, caratteristiche e dati ricevuti. Questo modello asincrono garantisce un'interfaccia utente non bloccante.

Stati di CBCentralManager

CBCentralManager attraversa diversi stati che determinano se lo stack BLE è disponibile. Lo stato viene trasmesso tramite il delegato: centralManagerDidUpdateState(_:). Lo sviluppatore deve gestire tutti gli stati — non solo poweredOn, ma anche i casi in cui Bluetooth è spento o non disponibile.

StatoValoreAzione dello sviluppatore
.poweredOnBluetooth è acceso e prontoAvviare scansione
.poweredOffBluetooth è spentoMostrare avviso all'utente
.unauthorizedNessun permessoRichiedere permesso in Impostazioni
.unsupportedDispositivo non supporta BLENascondere funzioni BLE
.unknownStato non definitoAspettare prossimo aggiornamento
.resettingBluetooth si sta riavviandoAspettare ripristino

Stato non autorizzato sta diventando sempre più comune da iOS 13+. A partire da questa versione, l'app deve avere il permesso NSBluetoothAlwaysUsageDescription in Info.plist. Senza di esso, il manager centrale passa allo stato .unauthorized e la scansione è impossibile. L'utente può modificare il permesso in Impostazioni > Privacy > Bluetooth in qualsiasi momento.

Scansione di dispositivi BLE

scanForPeripherals(withServices:options:) è il metodo principale per avviare la scansione. Il parametro withServices accetta un array di UUID di servizio per filtrare: se viene passato nil, tutti i dispositivi verranno scoperti, aumentando significativamente il consumo energetico. Si consiglia di filtrare sempre per gli UUID di servizio necessari all'app. Le opzioni di scansione includono CBCentralManagerScanOptionAllowDuplicatesKey (notifiche ripetute sullo stesso dispositivo).

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") // Servizio batteria

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

Quando un dispositivo viene scoperto, viene chiamato centralManager(_:didDiscover:advertisementData:rssi:). Il parametro advertisementData contiene il dizionario completo dei dati del pacchetto di pubblicità, inclusi il nome del dispositivo (CBAdvertisementDataLocalNameKey), gli UUID di servizio (CBAdvertisementDataServiceUUIDsKey) e i dati del produttore (CBAdvertisementDataManufacturerDataKey). RSSI è il livello del segnale in dBm disponibile al momento della scoperta.

Connessione a una periferica

connect(_:options:) è il metodo per stabilire una connessione BLE con una periferica scoperta. Dopo aver chiamato connect, iOS tenta di connettersi al dispositivo. Una connessione riuscita viene confermata tramite centralManager(_:didConnect:), un errore tramite centralManager(_:didFailToConnect:error:). Le opzioni di connessione includono CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey e CBConnectPeripheralOptionNotifyOnNotificationKey per notifiche in background.

swift
// Connetti al dispositivo BLE
func connectToPeripheral(
    _ peripheral: CBPeripheral
) {
    centralManager.connect(peripheral, options: nil)

    // Imposta delegato per periferica
    peripheral.delegate = self
}

// Delegato: connessione riuscita
func centralManager(
    _ central: CBCentralManager,
    didConnect peripheral: CBPeripheral
) {
    print("Connesso a " +
          "\(peripheral.name ?? "unknown")")

    // Avvia scoperta servizi
    peripheral.discoverServices(nil)
}

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

Il timeout di connessione su iOS è di 30 secondi. Se il dispositivo non ha risposto alla richiesta di connessione entro questo tempo, viene chiamato didFailToConnect. Il timeout è influenzato da: distanza dal dispositivo, interferenze e se il dispositivo sta attualmente pubblicizzando. Prima di connetterti, assicurati che il dispositivo sia in modalità pubblicità connettibile (ADV_IND, non ADV_NONCONN_IND).

Scoperta di servizi e caratteristiche

Dopo la connessione, è necessario scoprire i servizi (discoverServices) e le caratteristiche (discoverCharacteristics) della periferica. Questo è un passaggio obbligatorio prima di leggere o scrivere dati. Il processo è asincrono: discoverServices restituisce i risultati tramite peripheral(_:didDiscoverServices:), e discoverCharacteristics tramite peripheral(_:didDiscoverCharacteristicsFor:error:).

Si consiglia di passare un array di UUID pertinenti a discoverServices invece di nil. Il filtraggio accelera la scoperta e risparmia energia. Se un servizio non viene trovato, iOS segnalerà un array vuoto. Dopo aver scoperto le caratteristiche, è possibile leggere i loro valori (readValue), sottoscriversi alle notifiche (setNotifyValue) o scrivere dati (writeValue).

Una sfumatura importante: il MTU viene negoziato automaticamente dopo la connessione. Per ottenere il MTU corrente, usa peripheral.maximumWriteValueLength(for: .withResponse) o .withoutResponse. Su iOS, il MTU massimo è di 512 byte per dispositivi BLE 5.0. Se è necessario trasferire dati più grandi del MTU, implementa la frammentazione a livello di applicazione.

Scansione in background e limitazioni iOS

La scansione in background di dispositivi BLE su iOS richiede una configurazione speciale. Core Bluetooth supporta l'esecuzione in background, ma con limitazioni significative. Per lavorare in background, è necessario: attivare bluetooth-central in Background Modes nelle Capabilities del progetto, inizializzare CBCentralManager con l'opzione CBCentralManagerOptionRestoreIdentifierKey per il ripristino dello stato e gestire gli eventi del manager centrale quando si passa in background.

Limitazioni BLE in background su iOS: scanForPeripherals senza filtraggio UUID non funziona in background. L'app deve specificare UUID di servizio concreti per la scansione. iOS può ritardare la consegna degli eventi BLE indefinitamente. Core Bluetooth riprende automaticamente la scansione quando viene scoperto un dispositivo corrispondente, anche se l'app è in background. Timeout per la scansione in background: iOS può interrompere la scansione dopo 10–30 minuti per risparmiare energia.

State Restoration è un meccanismo di Core Bluetooth che consente di ripristinare le connessioni BLE dopo un riavvio dell'app o un riavvio di iOS. Per utilizzarlo: specifica CBCentralManagerOptionRestoreIdentifierKey durante l'inizializzazione, implementa centralManager(_:willRestoreState:) nel delegato e ripristina l'elenco delle periferiche connesse dal dizionario passato. State Restoration è una funzionalità critica per le app BLE che funzionano in background, come tracker fitness o dispositivi medici.

Gestione errori e recupero connessione

CBCentralManager genera errori in diversi scenari: connessione fallita (didFailToConnect), connessione persa (didDisconnectPeripheral), caratteristica non disponibile per lettura/scrittura (errore didWriteValue). Tutti gli errori di Core Bluetooth vengono restituiti tramite l'oggetto Error con dominio CBErrorDomain. I codici più comuni: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A).

Strategia di recupero connessione: quando ricevi didDisconnectPeripheral, controlla il codice di errore. Se l'errore è CBErrorConnectionTimeout o CBErrorPeripheralDisconnected — pianifica una riconnessione automatica dopo 1–5 secondi. Se l'errore è CBErrorOperationNotSupported — registralo e non ripetere l'operazione. Per connessioni critiche (dispositivi medici), usa backoff esponenziale con un intervallo massimo di 60 secondi.

swift
// Gestisci disconnessione con riconnessione automatica
func centralManager(
    _ central: CBCentralManager,
    didDisconnectPeripheral peripheral: CBPeripheral,
    error: Error?
) {
    guard let error = error else {
        return // Disconnessione prevista
    }

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

    // Riconnessione automatica
    if shouldAutoReconnect {
        DispatchQueue.main.asyncAfter(
            deadline: .now() + reconnectDelay
        ) {
            central.connect(peripheral)
        }
    }
}

Quando sviluppi un'app BLE robusta su iOS, tieni presente: Core Bluetooth non garantisce la consegna di tutti i pacchetti con segnale debole. Per una trasmissione affidabile, usa writeType .withResponse (scrittura confermata) e sottoscriviti alle notifiche (setNotifyValue) per ricevere dati dalla periferica. Mantieni un registro degli errori per diagnosticare problemi di connessione in produzione.

Domande Frequenti

Perché CBCentralManager non rileva i dispositivi?

Controlla lo stato del manager tramite centralManagerDidUpdateState. Assicurati che il permesso NSBluetoothAlwaysUsageDescription sia in Info.plist, che Bluetooth sia acceso sul dispositivo e che la periferica stia pubblicizzando con il tipo corretto (pubblicità connettibile, non non-connettibile).

Quanti dispositivi BLE possono essere collegati simultaneamente a iOS?

Su dispositivi con BLE 5.0 (iPhone 8 e successivi) — fino a 7 connessioni simultanee. Su dispositivi più vecchi — fino a 3–5. Il numero di dispositivi scansionati è illimitato, ma le connessioni attive hanno un limite rigido impostato dal Controller Bluetooth.

Con quale frequenza posso scansionare BLE su iOS senza scaricare la batteria?

Si consiglia di scansionare con filtraggio UUID e fermare la scansione quando il dispositivo viene trovato. La scansione continua scarica la batteria: 1 ora di scansione ininterrotta consuma ~10–15% della carica dell'iPhone. Usa timer e condizioni per fermare la scansione.

Qual è la differenza tra CBCentralManager e CBPeripheralManager?

CBCentralManager è per scansionare e connettersi a dispositivi BLE esterni (ruolo Central). CBPeripheralManager è per far sì che il tuo dispositivo iOS agisca come periferica BLE (pubblicizzi servizi). Un'istanza può essere solo in un ruolo.

Come gestire la perdita di connessione con un dispositivo BLE?

Implementa centralManager(_:didDisconnectPeripheral:error:). Se l'errore non è nil — pianifica una riconnessione automatica con backoff esponenziale (1 s → 2 s → 4 s → 8 s → max 60 s). Se l'errore è nil — il dispositivo si è disconnesso normalmente (ad esempio, l'utente ha premuto un pulsante sul dispositivo).

Riepilogo

  • CBCentralManager è la classe principale di Core Bluetooth per gestire scansione BLE, connessioni e trasferimento dati nel ruolo Central su iOS.
  • La scansione viene avviata tramite scanForPeripherals con filtraggio opzionale per UUID di servizio per ridurre il consumo energetico.
  • La connessione viene eseguita tramite connect, il successo è confermato da didConnect, l'errore da didFailToConnect con timeout di 30 secondi.
  • Dopo la connessione, è necessario scoprire servizi e caratteristiche tramite discoverServices e discoverCharacteristics.
  • La scansione in background richiede bluetooth-central Background Mode ed è supportata con limitazioni (filtraggio UUID, possibili ritardi).
  • iOS supporta fino a 7 connessioni BLE simultanee su dispositivi BLE 5.0, state restoration per il recupero dopo riavvio.
  • La gestione degli errori e la riconnessione automatica con backoff esponenziale sono alla base di un'app BLE affidabile su iOS.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche