CBCentralManager ist die zentrale Klasse des Core Bluetooth Frameworks in iOS, die das Scannen, Verbinden und Interagieren mit BLE-Peripheriegeräten verwaltet. Core Bluetooth (iOS 5+, 2011) bietet eine hochrangige Abstraktion über dem BLE-Stack auf GATT-Ebene und verbirgt die Details von Link Layer und HCI vor dem Entwickler. CBCentralManager implementiert die Central-Rolle: Er scannt die Luft über scanForPeripherals, initiiert Verbindungen über connect, entdeckt Dienste über discoverServices und verwaltet die Datenübertragung. Laut Apple Developer Documentation (2024) unterstützt CBCentralManager bis zu 7 gleichzeitige Verbindungen zu BLE-Geräten auf Geräten mit BLE 5.0.
Wichtige Punkte
CBCentralManager ist die Hauptklasse von Core Bluetooth zur Implementierung der Central-Rolle in der BLE-Architektur auf iOS. Er verwaltet den gesamten Lebenszyklus einer BLE-Verbindung: vom Scannen werbender Geräte bis zur Datenübertragung und Trennung. CBCentralManager arbeitet asynchron über den CBCentralManagerDelegate und benachrichtigt die App über Ereignisse im Bluetooth-Stack.
Die Initialisierung von CBCentralManager startet den State Restoration-Prozess: Der Manager prüft den Bluetooth-Status auf dem Gerät und stellt vorherige Verbindungen wieder her, wenn die App geschlossen wurde. Der Initialisierungsprozess kann je nach Bluetooth-Status 50 bis 500 ms dauern. Die App muss auf den Aufruf centralManagerDidUpdateState warten, bevor sie BLE-Operationen startet.
Die Core Bluetooth-Architektur basiert auf dem Delegation-Muster: CBCentralManager delegiert die Ereignisbehandlung (Geräteerkennung, Verbindung, Fehler) an das CBCentralManagerDelegate-Protokoll. Für die Arbeit mit einem bestimmten Peripheriegerät wird das CBPeripheralDelegate-Protokoll verwendet, das über entdeckte Dienste, Merkmale und empfangene Daten benachrichtigt. Dieses asynchrone Modell gewährleistet eine nicht blockierende Benutzeroberfläche.
CBCentralManager durchläuft mehrere Zustände, die bestimmen, ob der BLE-Stack verfügbar ist. Der Zustand wird über den Delegaten übermittelt: centralManagerDidUpdateState(_:). Der Entwickler muss alle Zustände behandeln – nicht nur poweredOn, sondern auch Fälle, in denen Bluetooth ausgeschaltet oder nicht verfügbar ist.
| Zustand | Wert | Entwickleraktion |
|---|---|---|
| .poweredOn | Bluetooth ist eingeschaltet und bereit | Scannen starten |
| .poweredOff | Bluetooth ist ausgeschaltet | Alert an Benutzer anzeigen |
| .unauthorized | Keine Berechtigung | Berechtigung in Einstellungen anfordern |
| .unsupported | Gerät unterstützt kein BLE | BLE-Funktionen ausblenden |
| .unknown | Zustand nicht definiert | Auf nächstes Update warten |
| .resetting | Bluetooth wird neu gestartet | Auf Wiederherstellung warten |
Nicht autorisierter Zustand wird seit iOS 13+ immer häufiger. Ab dieser Version muss die App die Berechtigung NSBluetoothAlwaysUsageDescription in Info.plist haben. Ohne sie wechselt der Central Manager in den Zustand .unauthorized, und das Scannen ist unmöglich. Der Benutzer kann die Berechtigung jederzeit unter Einstellungen > Datenschutz > Bluetooth ändern.
scanForPeripherals(withServices:options:) ist die Hauptmethode zum Starten des Scannens. Der Parameter withServices akzeptiert ein Array von Service-UUIDs zur Filterung: Wenn nil übergeben wird, werden alle Geräte erkannt, was den Stromverbrauch erheblich erhöht. Es wird empfohlen, immer nach den vom Benötigten Service-UUIDs zu filtern. Zu den Scan-Optionen gehört CBCentralManagerScanOptionAllowDuplicatesKey (wiederholte Benachrichtigungen über dasselbe Gerät).
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") // Batteriedienst
centralManager.scanForPeripherals(
withServices: [serviceUUID],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
}
Wenn ein Gerät erkannt wird, wird centralManager(_:didDiscover:advertisementData:rssi:) aufgerufen. Der Parameter advertisementData enthält das vollständige Wörterbuch der Werbepaketdaten, einschließlich des Gerätenamens (CBAdvertisementDataLocalNameKey), der Service-UUIDs (CBAdvertisementDataServiceUUIDsKey) und der Herstellerdaten (CBAdvertisementDataManufacturerDataKey). RSSI ist der Signalpegel in dBm zum Zeitpunkt der Erkennung.
connect(_:options:) ist die Methode zum Herstellen einer BLE-Verbindung zu einem erkannten Peripheriegerät. Nach dem Aufruf von connect versucht iOS, eine Verbindung zum Gerät herzustellen. Eine erfolgreiche Verbindung wird durch centralManager(_:didConnect:) bestätigt, ein Fehler durch centralManager(_:didFailToConnect:error:). Zu den Verbindungsoptionen gehören CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey und CBConnectPeripheralOptionNotifyOnNotificationKey für Hintergrundbenachrichtigungen.
// Mit BLE-Gerät verbinden
func connectToPeripheral(
_ peripheral: CBPeripheral
) {
centralManager.connect(peripheral, options: nil)
// Delegaten für Peripheriegerät festlegen
peripheral.delegate = self
}
// Delegat: erfolgreiche Verbindung
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
print("Verbunden mit " +
"\(peripheral.name ?? "unknown")")
// Diensterkennung starten
peripheral.discoverServices(nil)
}
// Delegat: Verbindungsfehler
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
print("Connection failed:
\(error?.localizedDescription ?? "")")
}
Das Verbindungstimeout auf iOS beträgt 30 Sekunden. Wenn das Gerät innerhalb dieser Zeit nicht auf die Verbindungsanfrage geantwortet hat, wird didFailToConnect aufgerufen. Das Timeout wird beeinflusst durch: Entfernung zum Gerät, Störungen und ob das Gerät gerade Werbung sendet. Stellen Sie vor dem Verbinden sicher, dass sich das Gerät im verbindbaren Werbemodus (ADV_IND, nicht ADV_NONCONN_IND) befindet.
Nach der Verbindung müssen Sie die Dienste (discoverServices) und Merkmale (discoverCharacteristics) des Peripheriegeräts entdecken. Dies ist ein obligatorischer Schritt vor dem Lesen oder Schreiben von Daten. Der Prozess ist asynchron: discoverServices gibt Ergebnisse über peripheral(_:didDiscoverServices:) zurück, und discoverCharacteristics über peripheral(_:didDiscoverCharacteristicsFor:error:).
Es wird empfohlen, ein Array relevanter UUIDs an discoverServices zu übergeben, anstatt nil. Die Filterung beschleunigt die Erkennung und spart Energie. Wenn ein Dienst nicht gefunden wird, meldet iOS ein leeres Array. Nach dem Entdecken der Merkmale können Sie deren Werte lesen (readValue), Benachrichtigungen abonnieren (setNotifyValue) oder Daten schreiben (writeValue).
Eine wichtige Nuance: Der MTU wird nach der Verbindung automatisch ausgehandelt. Verwenden Sie peripheral.maximumWriteValueLength(for: .withResponse) oder .withoutResponse, um den aktuellen MTU zu erhalten. Auf iOS beträgt der maximale MTU 512 Byte für BLE 5.0-Geräte. Wenn Sie Daten übertragen müssen, die größer als der MTU sind, implementieren Sie Fragmentierung auf Anwendungsebene.
Hintergrundscannen von BLE-Geräten auf iOS erfordert eine spezielle Konfiguration. Core Bluetooth unterstützt die Hintergrundausführung, jedoch mit erheblichen Einschränkungen. Für die Arbeit im Hintergrund müssen Sie: bluetooth-central in Background Modes in den Capabilities des Projekts aktivieren, CBCentralManager mit der Option CBCentralManagerOptionRestoreIdentifierKey für die Zustandswiederherstellung initialisieren und die Ereignisse des Central Managers beim Übergang in den Hintergrund behandeln.
Hintergrund-BLE-Einschränkungen auf iOS: scanForPeripherals ohne UUID-Filterung funktioniert im Hintergrund nicht. Die App muss konkrete Service-UUIDs für das Scannen angeben. iOS kann die Zustellung von BLE-Ereignissen auf unbestimmte Zeit verzögern. Core Bluetooth nimmt das Scannen automatisch wieder auf, wenn ein passendes Gerät erkannt wird, selbst wenn die App im Hintergrund ist. Timeout für Hintergrundscannen: iOS kann das Scannen nach 10–30 Minuten stoppen, um Energie zu sparen.
State Restoration ist ein Core Bluetooth-Mechanismus, der die Wiederherstellung von BLE-Verbindungen nach einem App-Neustart oder iOS-Neustart ermöglicht. Zur Verwendung: Geben Sie CBCentralManagerOptionRestoreIdentifierKey bei der Initialisierung an, implementieren Sie centralManager(_:willRestoreState:) im Delegaten und stellen Sie die Liste der verbundenen Peripheriegeräte aus dem übergebenen Wörterbuch wieder her. State Restoration ist eine kritische Funktion für BLE-Apps, die im Hintergrund arbeiten, wie Fitness-Tracker oder medizinische Geräte.
CBCentralManager generiert Fehler in mehreren Szenarien: Verbindung fehlgeschlagen (didFailToConnect), Verbindung getrennt (didDisconnectPeripheral), Merkmal nicht lesbar/schreibbar (didWriteValue-Fehler). Alle Core Bluetooth-Fehler werden über das Error-Objekt mit der Domäne CBErrorDomain zurückgegeben. Die häufigsten Codes: CBErrorConnectionTimeout (0x04), CBErrorPeripheralDisconnected (0x07), CBErrorOperationNotSupported (0x0A).
Strategie zur Verbindungswiederherstellung: Überprüfen Sie beim Empfang von didDisconnectPeripheral den Fehlercode. Wenn der Fehler CBErrorConnectionTimeout oder CBErrorPeripheralDisconnected ist, planen Sie eine automatische Wiederverbindung in 1–5 Sekunden. Wenn der Fehler CBErrorOperationNotSupported ist, protokollieren Sie ihn und wiederholen Sie den Vorgang nicht. Für kritische Verbindungen (medizinische Geräte) verwenden Sie exponentielles Backoff mit einem maximalen Intervall von 60 Sekunden.
// Trennung mit automatischer Wiederverbindung behandeln
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
guard let error = error else {
return // Erwartete Trennung
}
print("Disconnected: \(error.localizedDescription)")
// Automatische Wiederverbindung
if shouldAutoReconnect {
DispatchQueue.main.asyncAfter(
deadline: .now() + reconnectDelay
) {
central.connect(peripheral)
}
}
}
Bei der Entwicklung einer robusten BLE-App auf iOS beachten Sie: Core Bluetooth garantiert nicht die Zustellung aller Pakete bei schwachem Signal. Verwenden Sie für zuverlässige Übertragung writeType .withResponse (bestätigtes Schreiben) und abonnieren Sie Benachrichtigungen (setNotifyValue), um Daten vom Peripheriegerät zu empfangen. Führen Sie ein Fehlerprotokoll zur Diagnose von Verbindungsproblemen in der Produktion.
Häufig gestellte Fragen
Überprüfen Sie den Manager-Status über centralManagerDidUpdateState. Stellen Sie sicher, dass die Berechtigung NSBluetoothAlwaysUsageDescription in Info.plist vorhanden ist, Bluetooth auf dem Gerät aktiviert ist und das Peripheriegerät mit dem richtigen Typ wirbt (verbindbare Werbung, nicht nicht-verbindbar).
Auf Geräten mit BLE 5.0 (iPhone 8 und neuer) — bis zu 7 gleichzeitige Verbindungen. Auf älteren Geräten — bis zu 3–5. Die Anzahl der gescannten Geräte ist unbegrenzt, aber aktive Verbindungen haben eine vom Bluetooth-Controller festgelegte harte Grenze.
Es wird empfohlen, mit UUID-Filterung zu scannen und das Scannen zu stoppen, wenn das Gerät gefunden wurde. Kontinuierliches Scannen entlädt den Akku: 1 Stunde ununterbrochenes Scannen verbraucht ~10–15% der iPhone-Ladung. Verwenden Sie Timer und Bedingungen, um das Scannen zu stoppen.
CBCentralManager dient zum Scannen und Verbinden mit externen BLE-Geräten (Central-Rolle). CBPeripheralManager ermöglicht es Ihrem iOS-Gerät, selbst als BLE-Peripheriegerät zu fungieren (Dienste zu bewerben). Eine Instanz kann nur in einer Rolle sein.
Implementieren Sie centralManager(_:didDisconnectPeripheral:error:). Wenn der Fehler nicht nil ist, planen Sie eine automatische Wiederverbindung mit exponentiellem Backoff (1 s → 2 s → 4 s → 8 s → max 60 s). Wenn der Fehler nil ist, hat sich das Gerät normal getrennt (z.B. der Benutzer hat eine Taste am Gerät gedrückt).
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch