Core Bluetooth: arkitektur och BLE-utveckling på iOS

Författare: IT Sectr Publicerad: 2026-07-16 Lästid: 10 min

Core Bluetooth är Apples ramverk för interaktion med Bluetooth Low Energy på iOS, iPadOS och macOS. Ramverket tillhandahåller en komplett uppsättning API:er för arbete i båda BLE-rollerna: central enhet (CBCentralManager) för skanning och anslutning till kringutrustning och kringutrustning (CBPeripheralManager) för emulering av en BLE-server. Core Bluetooth abstraherar BLE-protokollstacken från fysisk radio till applikations-GATT-profil. Enligt Apple Developer, 2026 är Core Bluetooth det enda officiella Apple API:et för BLE-utveckling, med stöd för BLE 4.0–5.4 med extended advertising, 2M PHY och LE Audio.

Huvudpunkter

  • Core Bluetooth — Apples systemramverk för BLE-utveckling på iOS, iPadOS och macOS
  • CBCentralManager — klass för skanning och anslutning till BLE-kringutrustning från den centrala enheten
  • CBPeripheralManager — klass för att skapa en BLE-server som publicerar tjänster och egenskaper
  • GATT-profil — hierarkisk modell av tjänster, egenskaper och deskriptorer för datautbyte
  • Bakgrundslägen — Core Bluetooth stöder BLE-kommunikation i bakgrunden via systemdelegater och state restoration

Vad är Core Bluetooth: arkitektur och komponenter

Core Bluetooth delar upp BLE-stacken i två logiska roller definierade av Bluetooth SIG-specifikationen. Rollen som central enhet (Central) representeras av klassen CBCentralManager — initierar skanning, upprättar anslutningar och hanterar listan över anslutna CBPeripheral. Rollen som kringutrustning (Peripheral) representeras av CBPeripheralManager — publicerar tjänster och egenskaper, svarar på centralens förfrågningar och skickar notifikationer. En iOS-session kan samtidigt arbeta i båda rollerna på olika BLE-radioapparater, men en typisk app använder en roll.

Core Bluetooths arkitektur omfattar fem viktiga abstraktioner. CBCentralManager hanterar status för enhetens Bluetooth-adapter: poweredOn (redo att arbeta), poweredOff (Bluetooth avstängt), unauthorized (ingen behörighet), unsupported (BLE inte tillgängligt). CBPeripheral representerar en fjärr-BLE-enhet med dess UUID, namn, RSSI och GATT-hierarki. CBService — en logisk grupp av egenskaper. CBCharacteristic — en datapunkt för läsning/skrivning/notifikationer. CBPeripheralManager skapar en lokal GATT-server för emulering av kringutrustning.

KlassRollHuvudmetoder
CBCentralManagerCentral enhetscanForPeripherals, connect, cancelPeripheralConnection, retrievePeripherals
CBPeripheralFjärrkringutrustningdiscoverServices, discoverCharacteristics, readValue, writeValue, setNotifyValue
CBPeripheralManagerLokal kringutrustningaddService, removeService, startAdvertising, respondToRequest, updateValue
CBCentralFjärrcentralmaximumUpdateValueLength, identifier, ancsAuthorized

CBCentralManager-status hanterar alla BLE-operationer. När appen startar anropas centralManagerDidUpdateState med aktuell Bluetooth-status. Om status inte är .poweredOn ignoreras alla BLE-anrop av systemet. Utvecklaren måste kontrollera state före varje skanning och anslutning. Övergången från .poweredOff till .poweredOn sker när Bluetooth slås på i iOS-inställningar — delegaten får ett upprepat anrop och appen kan återuppta skanningen.

CBCentralManager: skanning och anslutning av BLE-enheter

CBCentralManager — ingångspunkten för alla BLE-operationer från den centrala enheten. Initiering tar emot en delegat (CBCentralManagerDelegate) och en DispatchQueue-kö — Apple rekommenderar att använda main queue för enkelhet eller serial queue för prestanda. Efter initiering kontrollerar ramverket automatiskt Bluetooth-status och anropar centralManagerDidUpdateState: — den första obligatoriska delegaten för bearbetning.

Skanning startas med metoden scanForPeripheralsWithServices:options:. Den första parametern är en array av CBUUID för tjänster för filtrering: om UUID för intressanta tjänster är kända minskar deras överföring energiförbrukning och söktid. Om nil detekteras alla BLE-enheter inom räckhåll. Alternativen inkluderar .allowDuplicatesKey (upprepad detektering av samma enhet) och .solicitedServiceUUIDsKey (för tjänster publicerade på centralen).

swift
import CoreBluetooth

class BLECentral: NSObject {

    private var centralManager: CBCentralManager!
    private var discoveredPeripherals: [CBPeripheral] = []

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

    // Starta BLE-skanning
    func startScan() {
        guard centralManager.state == .poweredOn else {
            print("Bluetooth inte tillgängligt")
            return
        }
        // Skanna alla enheter (nil = inget filter)
        centralManager.scanForPeripherals(withServices: nil,
                                            options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
    }

    // Stoppa skanning
    func stopScan() {
        centralManager.stopScan()
    }

    // Anslut till vald enhet
    func connect(to peripheral: CBPeripheral) {
        centralManager.connect(peripheral, options: nil)
    }
}

// MARK: - CBCentralManagerDelegate
extension BLECentral: CBCentralManagerDelegate {

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            startScan()
        }
    }

    func centralManager(_ central: CBCentralManager,
                        didDiscover peripheral: CBPeripheral,
                        advertisementData: [String : Any],
                        rssi: NSNumber) {
        if !discoveredPeripherals.contains(where: { $0.identifier == peripheral.identifier }) {
            discoveredPeripherals.append(peripheral)
            print("Found devices: \(peripheral.name ?? "Unknown"), RSSI: \(rssi)")
        }
    }

    func centralManager(_ central: CBCentralManager,
                        didConnect peripheral: CBPeripheral) {
        print("Connected: \(peripheral.identifier)")
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }

    func centralManager(_ central: CBCentralManager,
                        didDisconnectPeripheral peripheral: CBPeripheral,
                        error: Error?) {
        print("Disconnected: \(peripheral.identifier)")
    }
}

Klassen BLECentral demonstrerar hela cykeln för skanning och anslutning av BLE-enheter. centralManagerDidUpdateState startar skanning när Bluetooth är påslaget. didDiscoverPeripheral samlar in funna enheter i arrayen discoveredPeripherals med deduplicering enligt identifier. Efter anslutning (didConnect) startas omedelbart upptäckt av tjänster — detta är ett obligatoriskt steg före alla GATT-operationer.

CBPeripheralManager: skapa en BLE-server på iOS

CBPeripheralManager — klass för emulering av en BLE-kringutrustning på iOS. Appen i rollen som kringutrustning kan publicera sina egna tjänster och egenskaper, ta emot inkommande läs-/skrivförfrågningar från den centrala enheten och skicka notifikationer. CBPeripheralManager används för BLE-tillbehör som emuleras av iPhone: fjärrkontroller, tangentbord, spårare, IoT-gateways.

Livscykeln för CBPeripheralManager börjar med initiering och delegaten CBPeripheralManagerDelegate. Efter bekräftelse av poweredOn via peripheralManagerDidUpdateState: publiceras tjänster (addService:) och annonsering startas (startAdvertising:). Annonseringsdata CBAdvertisementData inkluderar lokalt namn (CBAdvertisementDataLocalNameKey), tjänste-UUID (CBAdvertisementDataServiceUUIDsKey) och effektnivå (CBAdvertisementDataTxPowerLevelKey). Maximal storlek för ett annonseringspaket är 31 byte för BLE 4.0, 251 byte för extended advertising BLE 5.0+.

swift
// BLE-kringutrustning på iOS via CBPeripheralManager
class BLEPeripheral: NSObject {

    private var peripheralManager: CBPeripheralManager!

    let serviceUUID = CBUUID(string: "1234")
    let characteristicUUID = CBUUID(string: "5678")

    override init() {
        super.init()
        peripheralManager = CBPeripheralManager(delegate: self, queue: .main)
    }

    // Publicera tjänst med egenskap
    func setupService() {
        let characteristic = CBMutableCharacteristic(
            type: characteristicUUID,
            properties: [.read, .write, .notify],
            value: nil,
            permissions: [.readable, .writeable]
        )
        let service = CBMutableService(type: serviceUUID, primary: true)
        service.characteristics = [characteristic]
        peripheralManager.add(service)
    }

    // Starta annonsering
    func startAdvertising() {
        let advertisementData: [String: Any] = [
            CBAdvertisementDataLocalNameKey: "My BLE Device",
            CBAdvertisementDataServiceUUIDsKey: [serviceUUID]
        ]
        peripheralManager.startAdvertising(advertisementData)
    }
}

// MARK: - CBPeripheralManagerDelegate
extension BLEPeripheral: CBPeripheralManagerDelegate {

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        if peripheral.state == .poweredOn {
            setupService()
        }
    }

    func peripheralManager(_ peripheral: CBPeripheralManager,
                        didAdd service: CBService,
                        error: Error?) {
        if error == nil {
            startAdvertising()
        }
    }

    // Hantera läsförfrågan
    func peripheralManager(_ peripheral: CBPeripheralManager,
                        didReceiveRead request: CBATTRequest) {
        let data = "CurrentValue".data(using: .utf8)!
        request.value = data
        peripheralManager.respond(to: request, withResult: .success)
    }

    // Hantera skrivförfrågan
    func peripheralManager(_ peripheral: CBPeripheralManager,
                        didReceiveWrite requests: [CBATTRequest]) {
        for request in requests {
            if let value = request.value {
                print("Write: \(value)")
            }
        }
        peripheralManager.respond(to: requests.first!, withResult: .success)
    }
}

Klassen BLEPeripheral skapar en BLE-server med en egenskap som stöder läsning, skrivning och notifikationer. Efter initiering publicerar peripheralManagerDidUpdateState tjänsten via addService: och startar sedan annonsering via startAdvertising:. Hanterarna didReceiveRead och didReceiveWrite svarar på inkommande GATT-förfrågningar från den centrala enheten. För att skicka notifikationer används metoden updateValue:forCharacteristic:onSubscribedCentrals:.

GATT-operationer: läsning, skrivning och notifikationer

GATT-operationer (Generic Attribute Profile) — grunden för datautbyte i Core Bluetooth. Efter upptäckt av tjänster och egenskaper kan den centrala enheten utföra tre typer av operationer: läsning av egenskapsvärde, skrivning av värde och prenumeration på notifikationer/indikationer. Varje operation är asynkron och returnerar resultatet via motsvarande CBPeripheralDelegate-delegat.

Läsning utförs genom att anropa readValueForCharacteristic:. Värdet anländer i peripheral:didUpdateValueForCharacteristic:error:. Viktigt: läsning returnerar aktuellt värde från enheten, inte cachat. Om enheten inte stöder läsning (egenskapen .read) returnerar anropet ett fel. För stora värden (större än MTU) fragmenterar och monterar BLE automatiskt data på GATT-nivå.

Skrivning utförs genom writeValue:forCharacteristic:type:. BLE stöder två skrivmodeller: withResponse (tillförlitlig, med bekräftelse) och withoutResponse (snabb, utan bekräftelse). Egenskapen CBCharacteristic.properties avgör tillgängliga skrivtyper. Maximal storlek för ett enskilt skrivpaket begränsas av MTU: 23 byte för BLE 4.0 (20 byte nyttodata + 3 byte huvud), upp till 247 byte för BLE 5.0 med extended MTU (MTU 251).

Notifikationer aktiveras genom att anropa setNotifyValue:true forCharacteristic:. Efter prenumeration skickar kringutrustningen automatiskt uppdateringar via peripheral:didUpdateValueForCharacteristic: varje gång egenskapsvärdet ändras. För att inaktivera notifikationer anropas setNotifyValue:false forCharacteristic:. Core Bluetooth hanterar automatiskt CCCD-deskriptorn på kringutrustningen.

OperationMetodDelegatÖverföringstyp
LäsningreadValueForCharacteristic:didUpdateValueForCharacteristicPolling (förfrågan-svar)
Skrivning withResponsewriteValue:forCharacteristic:type:withResponsedidWriteValueForCharacteristicMed bekräftelse
Skrivning withoutResponsewriteValue:forCharacteristic:type:withoutResponseIngen delegatUtan bekräftelse
NotifikationsetNotifyValue:true forCharacteristic:didUpdateNotificationStateForCharacteristic + didUpdateValueForCharacteristicPush från kringutrustning

Core Bluetooths bakgrundsläge och State Restoration

Bakgrundsläge Core Bluetooth tillåter BLE-appen att fortsätta skanna, upprätthålla anslutningar och ta emot notifikationer när den är i bakgrunden. För aktivering krävs: aktivera capability “Uses Bluetooth LE accessories” i Xcode (Info.plist → Required background modes → App communicates using Core Bluetooth) och lägg till nyckeln „bluetooth-central” i UIBackgroundModes. För kringutrustningsrollen — „bluetooth-peripheral”.

State Restoration — Core Bluetooths mekanism för att återställa status för BLE-anslutningar efter omstart av appen av iOS-systemet. Vid aktivering av bakgrundsläge och angivande av restoreIdentifier vid initiering av CBCentralManager eller CBPeripheralManager sparar iOS status för BLE-stacken vid appens avslutning och återställer den vid nästa start. Delegaten centralManager:willRestoreState: tar emot en ordbok med sparade CBPeripheral och väntande anslutningar.

swift
// Core Bluetooth-konfiguration med State Restoration
class BLECentralWithRestoration: NSObject {

    let restoreIdentifier = "com.app.blecentral"
    private var centralManager: CBCentralManager!

    override init() {
        super.init()
        let options: [String: Any] = [
            CBCentralManagerOptionRestoreIdentifierKey: restoreIdentifier,
            CBCentralManagerOptionShowPowerAlertKey: true
        ]
        centralManager = CBCentralManager(delegate: self,
                                          queue: nil,
                                          options: options)
    }
}

extension BLECentralWithRestoration: CBCentralManagerDelegate {

    // Återställ status efter omstart
    func centralManager(_ central: CBCentralManager,
                        willRestoreState dict: [String : Any]) {
        if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
            as? [CBPeripheral] {
            for peripheral in peripherals {
                peripheral.delegate = self
                // Återställ GATT-upptäckt
                peripheral.discoverServices(nil)
            }
        }
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            print("Bluetooth redo efter återställning")
        }
    }
}

I konfigurationen BLECentralWithRestoration aktiverar nyckeln CBCentralManagerOptionRestoreIdentifierKey lagring av status. Om appen avslutades av iOS (t.ex. på grund av minnesbrist), vid nästa start tar centralManager:willRestoreState: emot listan över tidigare anslutna CBPeripheral. Appen återställer delegater och utför återupptäckt av tjänster — användaren märker inte avbrott i anslutningen. Utan State Restoration förloras alla BLE-sessioner vid appens avslutning.

Exempel på BLE-app i Swift: central och kringutrustning

Fullständigt exempel på en BLE-app i Swift kombinerar central och kringutrustning i ett projekt. Appen kan fungera i två lägen: upptäcka och ansluta till BLE-enheter (Central) eller emulera ett BLE-tillbehör (Peripheral). Nedan visas arkitekturen med en gemensam BLE-hanterare som väljer roll vid start.

swift
// Universell BLE-hanterare för central och kringutrustning
class BLEManager {

    enum Role {
        case central
        case peripheral
    }

    private let role: Role
    private var centralManager: CBCentralManager?
    private var peripheralManager: CBPeripheralManager?
    let advertisedServiceUUID = CBUUID(string: "A001")

    init(role: Role) {
        self.role = role
        switch role {
        case .central:
            centralManager = CBCentralManager(delegate: nil, queue: .main)
        case .peripheral:
            peripheralManager = CBPeripheralManager(delegate: nil, queue: .main)
        }
    }

    // Central enhet: skanning
    func scanForDevices() {
        centralManager?.scanForPeripherals(withServices: nil, options: nil)
    }

    // Kringutrustning: annonsering
    func advertiseService() {
        let data: [String: Any] = [
            CBAdvertisementDataServiceUUIDsKey: [advertisedServiceUUID]
        ]
        peripheralManager?.startAdvertising(data)
    }
}

// Användning vid start
let isCentral = UserDefaults.standard.bool(forKey: "isCentral")
let manager = BLEManager(role: isCentral ? .central : .peripheral)

if isCentral {
    manager.scanForDevices()
} else {
    manager.advertiseService()
}

Hanteraren BLEManager väljer roll vid initiering och skapar motsvarande Manager (CBCentralManager eller CBPeripheralManager). Rollflaggan kan lagras i UserDefaults eller överföras via en konfigurationsserver. Detta tillvägagångssätt tillåter BLE-appen att anpassa sig till användningsscenariot: vid försäljningsstället fungerar iPhone som central för skanning av betalterminaler, på IoT-gatewayen — som kringutrustning för insamling av data från sensorer.

Vanliga frågor

Vad är Core Bluetooth?

Core Bluetooth — Apples ramverk för BLE-utveckling på iOS, iPadOS och macOS. Tillhandahåller API:er för drift av central (CBCentralManager) och kringutrustning (CBPeripheralManager). Stöder BLE 4.0–5.4, extended advertising, 2M PHY och LE Audio. Core Bluetooth är det enda officiella Apple API:et för BLE-kommunikation, obligatoriskt för alla iOS-appar som arbetar med Bluetooth Low Energy.

Vad är skillnaden mellan CBCentralManager och CBPeripheralManager?

CBCentralManager — klass för arbete i rollen som central enhet: skannar BLE-kringutrustning, upprättar anslutningar, läser och skriver egenskaper. CBPeripheralManager — klass för arbete i rollen som kringutrustning: publicerar tjänster, svarar på läs-/skrivförfrågningar och skickar notifikationer. En iPhone kan samtidigt arbeta i två roller via olika hanterarinstanser.

Hur konfigurerar man Core Bluetooth för bakgrundsarbete?

För BLE-bakgrundsarbete, aktivera capability „Uses Bluetooth LE accessories” i Xcode och lägg till nyckeln „bluetooth-central” i UIBackgroundModes. För kringutrustningsrollen — „bluetooth-peripheral”. Ange restoreIdentifier vid initiering av hanteraren för State Restoration. Utan dessa inställningar tar appen i bakgrunden inte emot BLE-händelser och förlorar anslutningar.

Varför hittar Core Bluetooth inga enheter?

Huvudorsaker: CBCentralManager.state != .poweredOn (Bluetooth avstängt eller inte auktoriserat), delegaten inte inställd, enheten utom räckhåll eller skickar inte annonseringspaket. Kontrollera behörigheten NSBluetoothAlwaysUsageDescription i Info.plist, Bluetooth-status i centralManagerDidUpdateState och se till att scanForPeripherals endast anropas vid .poweredOn.

Kan flera CBPeripheral anslutas samtidigt?

Ja, Core Bluetooth stöder samtidig anslutning till flera BLE-enheter. Varje CBPeripheral hanteras oberoende via sin egen delegat. iOS begränsar antalet samtidiga BLE-anslutningar på systemnivå (vanligtvis 5–7 för iPhone). För 1:N-scenarier (t.ex. ett fitnesscenter med 10 spårare) krävs köning och cyklisk betjäning av kringutrustning.

Sammanfattning

  • Core Bluetooth — Apples systemramverk för BLE-utveckling med klasserna CBCentralManager och CBPeripheralManager
  • CBCentralManager hanterar skanning, anslutning och GATT-operationer med fjärr-BLE-enheter
  • CBPeripheralManager emulerar BLE-kringutrustning med publicering av tjänster och bearbetning av inkommande förfrågningar
  • GATT-profil omfattar tjänster, egenskaper och deskriptorer med läs-, skriv- och notifikationsoperationer
  • Bakgrundsläge kräver UIBackgroundModes och restoreIdentifier för State Restoration
  • MTU BLE begränsar paketstorleken: 23 byte för BLE 4.0, upp till 251 byte för BLE 5.0+ med extended MTU
  • Swift async/await via CheckedContinuation förenklar asynkron BLE-kod med delegater

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också