Core Bluetoothは、iOS、iPadOS、macOSでBluetooth Low Energyと対話するためのAppleのフレームワークです。このフレームワークは、両方のBLEロールで動作するための完全なAPIセットを提供します:中央デバイス(CBCentralManager)は周辺機器のスキャンと接続用、周辺デバイス(CBPeripheralManager)はBLEサーバーのエミュレーション用です。Core Bluetoothは、物理無線からアプリケーションレベルのGATTプロファイルまで、BLEプロトコルスタックを抽象化します。Apple Developer、2026によると、Core BluetoothはBLE開発のための唯一の公式Apple APIであり、BLE 4.0–5.4、extended advertising、2M PHY、LE Audioをサポートしています。
重要なポイント
Core Bluetoothは、BLEスタックをBluetooth SIG仕様で定義された2つの論理ロールに分割します。中央デバイスのロール(Central)はCBCentralManagerクラスで表されます — スキャンを開始し、接続を確立し、接続されたCBPeripheralのリストを管理します。周辺デバイスのロール(Peripheral)はCBPeripheralManagerで表されます — サービスと特性を公開し、中央からの要求に応答し、通知を送信します。1つのiOSセッションは異なるBLE無線で両方のロールを同時に操作できますが、通常のアプリケーションは1つのロールを使用します。
Core Bluetoothアーキテクチャには5つの主要な抽象化が含まれています。CBCentralManagerはデバイスのBluetoothアダプターの状態を管理します:poweredOn(動作準備完了)、poweredOff(Bluetooth無効)、unauthorized(許可なし)、unsupported(BLE利用不可)。CBPeripheralは、UUID、名前、RSSI、GATT階層を持つリモートBLEデバイスを表します。CBService — 特性の論理グループ。CBCharacteristic — 読み取り/書き込み/通知のためのデータポイント。CBPeripheralManagerは周辺機器をエミュレートするためのローカルGATTサーバーを作成します。
| クラス | ロール | 主要メソッド |
|---|---|---|
| CBCentralManager | 中央デバイス | scanForPeripherals, connect, cancelPeripheralConnection, retrievePeripherals |
| CBPeripheral | リモート周辺 | discoverServices, discoverCharacteristics, readValue, writeValue, setNotifyValue |
| CBPeripheralManager | ローカル周辺 | addService, removeService, startAdvertising, respondToRequest, updateValue |
| CBCentral | リモート中央 | maximumUpdateValueLength, identifier, ancsAuthorized |
CBCentralManagerの状態はすべてのBLE操作を制御します。アプリが起動すると、centralManagerDidUpdateStateが現在のBluetooth状態で呼び出されます。状態が.poweredOnでない場合、システムはBLE呼び出しを無視します。開発者はスキャンと接続の前に状態を確認する必要があります。.poweredOffから.poweredOnへの遷移は、iOS設定でBluetoothが有効になったときに発生します — デリゲートが再度呼び出され、アプリはスキャンを再開できます。
CBCentralManagerは、中央デバイス側でのすべてのBLE操作のエントリポイントです。初期化はデリゲート(CBCentralManagerDelegate)とDispatchQueueを受け取ります — Appleはシンプルさのためにメインキュー、パフォーマンスのためにシリアルキューを推奨しています。初期化後、フレームワークは自動的にBluetooth状態をチェックし、centralManagerDidUpdateState:を呼び出します — 処理する最初の必須デリゲートです。
スキャンはscanForPeripheralsWithServices:options:メソッドで開始されます。最初のパラメータはフィルタリング用のCBUUIDサービスの配列です:目的のサービスのUUIDがわかっている場合、それを渡すと消費電力と検索時間が削減されます。nilの場合は、範囲内のすべてのBLEデバイスが検出されます。オプションには、.allowDuplicatesKey(同じデバイスの重複検出)と.solicitedServiceUUIDsKey(中央で公開されるサービス用)が含まれます。
import CoreBluetooth
class BLECentral: NSObject {
private var centralManager: CBCentralManager!
private var discoveredPeripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: .main)
}
// BLEスキャンを開始
func startScan() {
guard centralManager.state == .poweredOn else {
print("Bluetoothが利用できません")
return
}
// すべてのデバイスをスキャン(nil = フィルターなし)
centralManager.scanForPeripherals(withServices: nil,
options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
}
// スキャンを停止
func stopScan() {
centralManager.stopScan()
}
// 選択したデバイスに接続
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)")
}
}
BLECentralクラスは、BLEデバイスのスキャンと接続の完全なサイクルを示しています。centralManagerDidUpdateStateはBluetoothが有効なときにスキャンを開始します。didDiscoverPeripheralは、identifierによる重複排除を行い、見つかったデバイスをdiscoveredPeripherals配列に収集します。接続(didConnect)後、すぐにサービス検出が開始されます — これはGATT操作の前の必須ステップです。
CBPeripheralManagerは、iOSでBLE周辺デバイスをエミュレートするためのクラスです。周辺ロールのアプリは、サービスと特性を公開し、中央デバイスからの読み取り/書き込み要求を受け入れ、通知を送信できます。CBPeripheralManagerはiPhoneでエミュレートされるBLEアクセサリに使用されます:リモコン、キーボード、トラッカー、IoTゲートウェイなど。
CBPeripheralManagerのライフサイクルは、初期化とCBPeripheralManagerDelegateから始まります。peripheralManagerDidUpdateState:を介してpoweredOnの確認を受けた後、サービスが公開され(addService:)、アドバタイジングが開始されます(startAdvertising:)。アドバタイジングデータCBAdvertisementDataには、ローカル名(CBAdvertisementDataLocalNameKey)、サービスUUID(CBAdvertisementDataServiceUUIDsKey)、送信電力レベル(CBAdvertisementDataTxPowerLevelKey)が含まれます。最大アドバタイジングパケットサイズは、BLE 4.0で31バイト、extended advertising BLE 5.0+で251バイトです。
// CBPeripheralManagerを介したiOS上のBLE周辺機器
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)
}
// 特性を持つサービスを公開
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)
}
// アドバタイジングを開始
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()
}
}
// 読み取り要求を処理
func peripheralManager(_ peripheral: CBPeripheralManager,
didReceiveRead request: CBATTRequest) {
let data = "CurrentValue".data(using: .utf8)!
request.value = data
peripheralManager.respond(to: request, withResult: .success)
}
// 書き込み要求を処理
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)
}
}
BLEPeripheralクラスは、読み取り、書き込み、通知をサポートする単一の特性を持つBLEサーバーを作成します。初期化後、peripheralManagerDidUpdateStateはaddService:を介してサービスを公開し、次にstartAdvertising:を介してアドバタイジングを開始します。didReceiveReadとdidReceiveWriteハンドラは、中央デバイスからの着信GATT要求に応答します。通知の送信にはupdateValue:forCharacteristic:onSubscribedCentrals:メソッドが使用されます。
GATT操作(Generic Attribute Profile)は、Core Bluetoothにおけるデータ交換の基盤です。サービスと特性の検出後、中央デバイスは3種類の操作を実行できます:特性値の読み取り、値の書き込み、通知/ indicationの購読。各操作は非同期で、対応するCBPeripheralDelegateコールバックを介して結果を返します。
読み取り:readValueForCharacteristic:を呼び出して実行します。値はperipheral:didUpdateValueForCharacteristic:error:で到着します。重要:読み取りはデバイスから現在の値を返し、キャッシュされた値ではありません。デバイスが読み取りをサポートしていない場合(.readプロパティ)、呼び出しはエラーを返します。大きな値(MTUより大きい)の場合、BLEは自動的にGATTレベルでデータを分割して再構成します。
書き込み:writeValue:forCharacteristic:type:を呼び出して実行します。BLEは2つの書き込みモデルをサポートしています:withResponse(信頼性高、確認応答あり)とwithoutResponse(高速、確認応答なし)。CBCharacteristic.propertiesプロパティが利用可能な書き込みタイプを定義します。単一の書き込みパケットの最大サイズはMTUによって制限されます:BLE 4.0で23バイト(20バイトのペイロード+3バイトのヘッダー)、拡張MTU(MTU 251)のBLE 5.0で最大247バイト。
通知:setNotifyValue:true forCharacteristic:を呼び出して有効化します。購読後、周辺機器は特性値が変更されるたびに、peripheral:didUpdateValueForCharacteristic:を介して自動的に更新を送信します。通知を無効にするには、setNotifyValue:false forCharacteristic:を呼び出します。Core Bluetoothは周辺機器のCCCDディスクリプタを自動的に管理します。
| 操作 | メソッド | デリゲート | 転送タイプ |
|---|---|---|---|
| 読み取り | readValueForCharacteristic: | didUpdateValueForCharacteristic | ポーリング(要求-応答) |
| withResponse書き込み | writeValue:forCharacteristic:type:withResponse | didWriteValueForCharacteristic | 確認応答あり |
| withoutResponse書き込み | writeValue:forCharacteristic:type:withoutResponse | デリゲートなし | 確認応答なし |
| 通知 | setNotifyValue:true forCharacteristic: | didUpdateNotificationStateForCharacteristic + didUpdateValueForCharacteristic | 周辺からのプッシュ |
バックグラウンドモードでは、Core Bluetoothを使用するBLEアプリがバックグラウンドにいる間もスキャンを継続し、接続を維持し、通知を受信できます。有効にするには、Xcodeで“Uses Bluetooth LE accessories”機能を有効にし(Info.plist → Required background modes → App communicates using Core Bluetooth)、UIBackgroundModesに“bluetooth-central”キーを追加します。周辺ロールの場合は—“bluetooth-peripheral”。
State Restorationは、iOSによるアプリ再起動後にBLE接続の状態を復元するためのCore Bluetoothのメカニズムです。バックグラウンドモードがアクティブで、CBCentralManagerまたはCBPeripheralManagerの初期化でrestoreIdentifierが指定されている場合、iOSはアプリ終了時にBLEスタックの状態を保存し、次回起動時に復元します。デリゲートcentralManager:willRestoreState:は、保存されたCBPeripheralと保留中の接続を含む辞書を受け取ります。
// State Restorationを使用したCore Bluetoothの設定
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 {
// 再起動後に状態を復元
func centralManager(_ central: CBCentralManager,
willRestoreState dict: [String : Any]) {
if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]
as? [CBPeripheral] {
for peripheral in peripherals {
peripheral.delegate = self
// GATT検出を復元
peripheral.discoverServices(nil)
}
}
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("復元後にBluetooth準備完了")
}
}
}
BLECentralWithRestoration構成では、CBCentralManagerOptionRestoreIdentifierKeyキーが状態保存を有効にします。アプリがiOSによって終了された場合(メモリ不足など)、次回起動時にcentralManager:willRestoreState:は以前に接続されたCBPeripheralのリストを受け取ります。アプリはデリゲートを復元し、サービスの再検出を実行します — ユーザーは接続の中断に気づきません。State Restorationがない場合、アプリ終了時にすべてのBLEセッションが失われます。
完全な例として、SwiftのBLEアプリが中央デバイスと周辺デバイスの両方を1つのプロジェクトに統合しています。アプリは2つのモードで動作できます:BLEデバイスを検出して接続する(中央)、またはBLEアクセサリをエミュレートする(周辺)。以下は、起動時にロールを選択する共通のBLEマネージャーを使用したアーキテクチャです。
// 中央と周辺のためのユニバーサルBLEマネージャー
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)
}
}
// 中央デバイス:スキャン
func scanForDevices() {
centralManager?.scanForPeripherals(withServices: nil, options: nil)
}
// 周辺デバイス:アドバタイジング
func advertiseService() {
let data: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [advertisedServiceUUID]
]
peripheralManager?.startAdvertising(data)
}
}
// 起動時の使用
let isCentral = UserDefaults.standard.bool(forKey: "isCentral")
let manager = BLEManager(role: isCentral ? .central : .peripheral)
if isCentral {
manager.scanForDevices()
} else {
manager.advertiseService()
}
BLEManagerは初期化時にロールを選択し、対応するManager(CBCentralManagerまたはCBPeripheralManager)を作成します。ロールフラグはUserDefaultsに保存するか、構成サーバーを介して渡すことができます。このアプローチにより、BLEアプリはユースケースに適応できます:販売時点ではiPhoneが中央として支払い端末をスキャンし、IoTゲートウェイでは周辺としてセンサーからデータを収集します。
よくある質問
Core Bluetoothは、iOS、iPadOS、macOS向けBLE開発のためのAppleのフレームワークです。中央(CBCentralManager)と周辺(CBPeripheralManager)の両方のデバイスにAPIを提供します。BLE 4.0–5.4、extended advertising、2M PHY、LE Audioをサポートしています。Core BluetoothはBLE通信のための唯一の公式Apple APIであり、Bluetooth Low Energyを扱うすべてのiOSアプリに必要です。
CBCentralManagerは中央デバイスロールで動作するためのクラスです:BLE周辺機器をスキャンし、接続を確立し、特性を読み書きします。CBPeripheralManagerは周辺ロールで動作するためのクラスです:サービスを公開し、読み取り/書き込み要求に応答し、通知を送信します。1台のiPhoneは異なるマネージャーインスタンスを通じて両方のロールを同時に実行できます。
バックグラウンドBLE動作には、Xcodeで“Uses Bluetooth LE accessories”機能を有効にし、UIBackgroundModesに“bluetooth-central”キーを追加します。周辺ロールの場合は—“bluetooth-peripheral”。State Restorationのためにマネージャーを初期化する際にrestoreIdentifierを指定します。これらの設定がないと、バックグラウンドのアプリはBLEイベントを受信できず、接続が失われます。
一般的な理由:CBCentralManager.state != .poweredOn(Bluetoothが無効または未承認)、デリゲートが設定されていない、デバイスが範囲外またはアドバタイジングパケットを送信していない。Info.plistのNSBluetoothAlwaysUsageDescription権限、centralManagerDidUpdateStateのBluetoothステータスを確認し、scanForPeripheralsが.poweredOnの場合にのみ呼び出されるようにしてください。
はい、Core Bluetoothは複数のBLEデバイスへの同時接続をサポートしています。各CBPeripheralは独自のデリゲートを通じて独立して管理されます。iOSはシステムレベルで同時BLE接続数を制限します(通常iPhoneで5~7)。1:Nのシナリオ(10個のトラッカーがあるフィットネスセンターなど)では、周辺機器をキューに入れて循環的にサービスする必要があります。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。