CBPeripheral, iOS'ta uzak bir BLE cihazını temsil eden Core Bluetooth framework sınıfıdır. Her CBPeripheral nesnesi, bağlı bir BLE cihazının UUID'sini, adını, RSSI'sini ve GATT hizmet hiyerarşisini kapsüller. Geliştirici, çevre birimiyle yalnızca CBPeripheral aracılığıyla etkileşime girer: hizmet keşfi (discoverServices:), karakteristik okuma (readValueForCharacteristic:), veri yazma (writeValue:forCharacteristic:type:) ve bildirim aboneliği (setNotifyValue:forCharacteristic:). Apple Developer, 2026'ya göre CBPeripheral, bir cihaz keşfedildiğinde veya bağlandığında CBCentralManager tarafından döndürülen, tüm BLE çevre birimi işlemleri için merkezi nesnedir.
Önemli Noktalar
CBPeripheral, bir iOS uygulamasında uzak bir BLE cihazını temsil eden bir nesnedir. iPhone'un yerel Bluetooth adaptörünü yöneten CBCentralManager'ın aksine, CBPeripheral harici bir çevre birimi cihazını modeller: bir sensör, fitness takip cihazı, işaretçi veya tıbbi cihaz. Her CBPeripheral örneği, bağlantı oturumları arasında kalıcı olan benzersiz bir tanımlayıcı (UUID) içerir — Apple, UUID'yi sistem Bonding'i aracılığıyla belirli bir cihaza bağlar.
CBPeripheral doğrudan init aracılığıyla oluşturulmaz. Core Bluetooth framework'ü, CBPeripheral nesnesini iki senaryoda döndürür: bir cihaz scanForPeripheralsWithServices: aracılığıyla keşfedildiğinde (delege didDiscoverPeripheral) ve retrievePeripheralsWithIdentifiers: aracılığıyla önceden bilinen bir cihaza bağlanıldığında. Nesne alındıktan sonra, geliştirici CBCentralManager üzerinde connectPeripheral: çağrısını yapar ve ardından CBPeripheral GATT işlemleri için kullanılabilir hale gelir.
CBPeripheral Yaşam Döngüsü altı durum içerir: bağlantı kesik (başlangıç), bağlanıyor (connect çağrısından sonra), bağlı (didConnectPeripheral'den sonra), keşfediyor (discoverServices çağrısı sırasında), keşfedildi (hizmetler alındıktan sonra) ve bağlantı kesiyor (cancelPeripheralConnection'dan sonra). Her durum, CBPeripheralDelegate protokolü aracılığıyla izlenir — iOS'taki herhangi bir BLE uygulaması için olmazsa olmazdır.
CBPeripheral, üç seviyeden oluşan hiyerarşik bir GATT yapısı depolar. Kök seviye, bir CBService (hizmet) dizisidir, her hizmet bir CBCharacteristic (karakteristik) dizisi içerir, her karakteristik bir CBDescriptor (tanımlayıcı) dizisi içerir. Bu model, Bluetooth GATT spesifikasyonuna tamamen uygundur: bir hizmet, bir cihaz işlevidir (örneğin, “Kalp Atış Hızı Servisi”), bir karakteristik belirli bir değerdir (nabız 72 bpm), bir tanımlayıcı karakteristik meta verileridir (ölçüm birimleri, bildirim yapılandırması).
| Seviye | Core Bluetooth Sınıfı | Açıklama |
|---|---|---|
| Hizmet | CBService | İlgili karakteristiklerin mantıksal grubu, UUID (16-bit, 32-bit veya 128-bit) ile tanımlanır |
| Karakteristik | CBCharacteristic | Belirli veri değeri, okuma, yazma ve bildirimleri destekler |
| Tanımlayıcı | CBDescriptor | Karakteristik meta verileri: istemci yapılandırması CCCD, kullanıcı açıklaması, sunum formatı |
Standart BLE hizmetleri Bluetooth SIG tarafından kaydedilmiştir: Heart Rate Service (UUID 180D), Battery Service (180F), Device Information (180A), Blood Pressure (1810). Özel hizmetler için 128-bit UUID'ler kullanılır (örneğin, E20A39F4-73F5-4BC4-A12F-17D1AD07A961). iOS, standart UUID'leri otomatik olarak tanır ve insan tarafından okunabilir adlar görüntüler; özel UUID'ler onaltılık formatta görünür.
Bağlantıdan sonra, CBPeripheral hiyerarşisi boştur — hizmetler ve karakteristikler yüklenmemiştir. Geliştirici, hizmetleri almak için discoverServices: çağrısını ve ardından her hizmet için discoverCharacteristics:forService: çağrısını yapmalıdır. Hizmet, dahil edilen hizmetler içeriyorsa, ayrıca discoverIncludedServices:forService: çağrılır. Hiyerarşi keşfi tamamlandıktan sonra CBPeripheral doldurulur ve okuma ve yazma için kullanılabilir hale gelir.
Keşif CBPeripheral'ın GATT yapısının keşfi, herhangi bir okuma veya yazma işleminden önce zorunlu bir adımdır. discoverServices: yöntemi, tüm cihaz hizmetlerinin asenkron bir aramasını başlatır. Nil iletilirse, tüm hizmetler keşfedilir; bir CBUUID dizisi iletilirse — yalnızca belirtilen UUID'lere sahip hizmetler (zaman optimizasyonu). Sonuç, delege peripheral:didDiscoverServices:'a gelir — CBPeripheral nesnesi, services özelliğini bir CBService dizisiyle doldurur.
Hizmetler alındıktan sonra, her CBService için discoverCharacteristics:forService: çağrılmalıdır. Benzer şekilde, nil — tüm karakteristikler, CBUUID dizisi — yalnızca belirtilenler. Sonuç: peripheral:didDiscoverCharacteristicsForService:error:. Bu aşamada, CBCharacteristic, izin verilen işlemleri tanımlayan özellikler (properties: .read, .write, .notify, .indicate) alır.
import CoreBluetooth
extension BLEViewController: CBPeripheralDelegate {
// 1. Service discovery
func peripheral(_ peripheral: CBPeripheral,
didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
// Request characteristics for each service
peripheral.discoverCharacteristics(nil, for: service)
}
}
// 2. Characteristic discovery
func peripheral(_ peripheral: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?) {
guard let characteristics = service.characteristics else { return }
for characteristic in characteristics {
if characteristic.properties.contains(.read) {
peripheral.readValue(for: characteristic)
}
if characteristic.properties.contains(.notify) {
peripheral.setNotifyValue(true, for: characteristic)
}
}
}
// 3. Read value
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
guard let data = characteristic.value,
let value = String(data: data, encoding: .utf8)
else { return }
print("Characteristic value: \(value)")
}
}
Örnekte, CBPeripheralDelegate üç zorunlu keşif yöntemini uygular. didDiscoverServices, bulunan tüm hizmetler üzerinde yinelenir ve karakteristikleri ister. didDiscoverCharacteristicsForService, her karakteristiğin özelliklerini kontrol eder: .read için readValue'yu, .notify için setNotifyValue(true)'u çağırır. didUpdateValueForCharacteristic yöntemi, Data formatında gerçek değeri alır.
Değer Okuma CBCharacteristic değerinin okunması, readValueForCharacteristic: yöntemi kullanılarak gerçekleştirilir. Sonuç, asenkron olarak peripheral:didUpdateValueForCharacteristic:error:'a gelir. Önemli: cihazda önbelleğe alınmış bir değer olabilir (karakteristik keşfinden hemen sonra characteristic.value kullanılabilir), ancak güncel veriyi almak için readValue çağrısı zorunludur. iOS, enerji verimliliği için değerleri önbelleğe alabilir — readValue önbelleği yeniler.
Değer Yazma, writeValue:forCharacteristic:type: yöntemi kullanılarak gerçekleştirilir. type parametresi yazma türünü belirler: .withResponse (CBCharacteristicWriteWithResponse) — cihaz, didWriteValueForCharacteristic aracılığıyla yazmayı onaylar; .withoutResponse (CBCharacteristicWriteWithoutResponse) — onaysız yazma, maksimum hız ancak teslimat garantisi yoktur. BLE spesifikasyonu, MTU'yu (Maksimum İletim Birimi) sınırlar: BLE 4.0 için 23 bayta kadar, BLE 5.0+ için 251 bayta kadar. MTU'dan büyük veriler için uygulama düzeyinde parçalama gereklidir.
// CBPeripheral characteristic read and write
class BLEService {
private let peripheral: CBPeripheral
private let serviceUUID = CBUUID(string: "180D")
private let charUUID = CBUUID(string: "2A37")
init(peripheral: CBPeripheral) {
self.peripheral = peripheral
}
// Read with response
func readHeartRate() {
guard let service = peripheral.services?.first(where: { $0.uuid == serviceUUID }),
let characteristic = service.characteristics?.first(where: { $0.uuid == charUUID })
else { return }
peripheral.readValue(for: characteristic)
}
// Write with response (withResponse)
func writeWithResponse(data: Data) {
guard let characteristic = findCharacteristic() else { return }
peripheral.writeValue(data, for: characteristic,
type: .withResponse)
}
// Write without response (withoutResponse)
// Max throughput, no delivery guarantee
func writeWithoutResponse(data: Data) {
guard let characteristic = findCharacteristic() else { return }
peripheral.writeValue(data, for: characteristic,
type: .withoutResponse)
}
private func findCharacteristic() -> CBCharacteristic? {
return peripheral.services?
.flatMap { $0.characteristics ?? [] }
.first(where: { $0.uuid == charUUID })
}
}
Yazma türü withResponse veya withoutResponse seçimi, güvenilirlik gereksinimlerine bağlıdır. Komutlar için (ışığı açmak, kilidi açmak) withResponse kullanın — teslimat garantisi kritiktir. Akış verileri için (nabız, sıcaklık) withoutResponse kullanın — bir paketin kaybı önemsizdir. Bir BLE cihazı yalnızca bir yazma türünü destekleyebilir — characteristic.properties.contains(.write) ve .writeWithoutResponse özelliklerini kontrol edin.
Bildirimler, çevre birimi cihazının karakteristik değerlerini merkez cihaza asenkron olarak gönderdiği bir BLE mekanizmasıdır ve merkez tarafından sürekli yoklama yapılmaz. CBPeripheral, setNotifyValue:forCharacteristic: yöntemi aracılığıyla aboneliği etkinleştirir. Abonelik etkinleştirildikten sonra, iOS otomatik olarak çevre birimindeki CCCD'ye (İstemci Karakteristik Yapılandırma Tanımlayıcısı) yazar ve cihaz, değer her değiştiğinde güncellemeler göndermeye başlar.
İndikasyonların aksine, bildirimler merkez cihazdan onay gerektirmez — paket gönderilir ve unutulur. Bu, maksimum verim sağlar ancak paket kaybı mümkündür. İndikasyonlar, protokol düzeyinde (L2CAP) onay gerektirir — daha güvenilir ancak daha yavaştır. CBCharacteristic'in properties özelliği, hangi modun desteklendiğini tam olarak belirtir: .notify, .indicate veya her ikisi.
CBPeripheral bağlantısı kesildiğinde (bağlantı kesme, menzil dışı), tüm aktif abonelikler otomatik olarak sıfırlanır. Yeniden bağlanıldığında, her karakteristik için tekrar setNotifyValue:true çağrılmalıdır. iOS, uygulama ön plandan çıktığında da abonelikleri kaybeder (arka plan modu etkin değilse) — arka plan çalışması için Info.plist'te “Uses Bluetooth LE accessories” yeteneği etkinleştirilmelidir.
// CBPeripheral notification subscription management
class NotificationManager: NSObject {
private var peripheral: CBPeripheral?
private var subscribedCharacteristics: Set<CBUUID> = []
// Subscribe to notifications for all .notify characteristics
func subscribeToAllNotifications(peripheral: CBPeripheral) {
self.peripheral = peripheral
guard let services = peripheral.services else { return }
for service in services {
guard let characteristics = service.characteristics else { continue }
for characteristic in characteristics {
if characteristic.properties.contains(.notify)
|| characteristic.properties.contains(.indicate) {
peripheral.setNotifyValue(true, for: characteristic)
subscribedCharacteristics.insert(characteristic.uuid)
}
}
}
}
// Unsubscribe from all notifications
func unsubscribeFromAll() {
guard let peripheral = peripheral else { return }
guard let services = peripheral.services else { return }
for service in services {
guard let characteristics = service.characteristics else { continue }
for characteristic in characteristics {
if subscribedCharacteristics.contains(characteristic.uuid) {
peripheral.setNotifyValue(false, for: characteristic)
}
}
}
subscribedCharacteristics.removeAll()
}
// Notification handler
func peripheral(_ peripheral: CBPeripheral,
didUpdateNotificationStateFor characteristic: CBCharacteristic,
error: Error?) {
if characteristic.isNotifying {
print("Subscription active: \(characteristic.uuid)")
} else {
print("Subscription inactive: \(characteristic.uuid)")
}
}
}
NotificationManager, CBPeripheral bildirimlerinin doğru şekilde işlenmesini gösterir. subscribeToAllNotifications, tüm hizmetler ve karakteristikler üzerinde yinelenir, .notify ve .indicate'i etkinleştirir. subscribedCharacteristics, doğru abonelik iptali için aktif abonelikleri izler. didUpdateNotificationStateForCharacteristic, characteristic.isNotifying özelliği aracılığıyla başarılı abonelik durumu değişikliğini onaylar.
Tam İş Akışı CBPeripheral ile: CBCentralManager'dan nesne alma, bağlantı, keşif, okuma/yazma, bildirim aboneliği ve bağlantı kesme. Aşağıdaki örnek, modern async/await API'sini (iOS 15+) kullanarak Swift'te tam bir BLE çevre birimi yaşam döngüsünü yöneten BLEConnection sınıfını uygular.
import CoreBluetooth
// Full CBPeripheral management example with async/await
class BLEConnection: NSObject {
private let centralManager: CBCentralManager
private var peripheral: CBPeripheral?
private var continuation: CheckedContinuation<Void, Error>?
override init() {
centralManager = CBCentralManager(delegate: nil, queue: .main)
super.init()
centralManager.delegate = self
}
// 1. Connect to peripheral
func connect(to peripheral: CBPeripheral) async throws {
self.peripheral = peripheral
peripheral.delegate = self
centralManager.connect(peripheral, options: nil)
try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
}
}
// 2. Discovery
func discoverServices() async throws {
guard let peripheral = peripheral else {
throw BLEError.notConnected
}
peripheral.discoverServices(nil)
try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
}
}
}
// 3. CBCentralManager
extension BLEConnection: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
// Handle Bluetooth device state
}
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
continuation?.resume()
continuation = nil
}
func centralManager(_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?) {
continuation?.resume(throwing: error ?? BLEError.connectionFailed)
continuation = nil
}
}
enum BLEError: Error {
case notConnected
case connectionFailed
case serviceNotFound
case characteristicNotFound
}
BLEConnection sınıfı, CheckedContinuation aracılığıyla Swift Concurrency (async/await) kullanır — Core Bluetooth'un delege tabanlı API'si ile çalışmak için modern bir desen. connect(to:), didConnectPeripheral aracılığıyla bağlantı onayını bekler, discoverServices() — didDiscoverServices aracılığıyla. Bu yaklaşım, iç içe geçmiş delegeleri ortadan kaldırır ve BLE kodunu doğrusal ve okunabilir hale getirir. BLEError aracılığıyla hata işleme, tüm tipik BLE bağlantı hatası senaryolarını kapsar.
Sıkça Sorulan Sorular
CBPeripheral, daha önce bağlanmış bir cihaz için CBCentralManager üzerinde retrievePeripheralsWithIdentifiers: aracılığıyla alınabilir. Daha önce kaydedilmiş cihazların UUID (NSUUID) dizisini iletin — framework, sistem BLE bonding veritabanındaki cihazlar için bir CBPeripheral dizisi döndürür. Bu yalnızca iPhone'un daha önce eşleştirdiği cihazlarla çalışır. Yeni bir cihaz için tarama zorunludur.
Yaygın nedenler: cihaz menzil dışında (RSSI eşik değerinin altında), BLE radyosu kapalı (CBCentralManager.state != .poweredOn), CBPeripheralDelegate ayarlanmamış (peripheral.delegate = self) veya discoverServices bağlantıdan önce çağrılmış. centralManager.state'i kontrol edin, connect çağrısından önce delegenin ayarlandığından emin olun ve 5–10 saniye zaman aşımı ile yeniden deneme kullanın.
Nedeni, yalnızca .writeWithoutResponse destekleyen bir karakteristikte .withResponse kullanmaktır veya tam tersi. Çağrıdan önce characteristic.properties'i kontrol edin. Diğer bir olası sorun MTU'dur: veri 20 baytı (BLE 4.0 MTU) aşarsa, negotiateMTU veya parçalama yoluyla MTU müzakeresi gereklidir. Maksimum paket boyutunu belirlemek için peripheral.maximumWriteValueLength(for: .withResponse) kullanın.
Menzil dışındaki CBPeripheral hemen bağlantıyı kesmez — iOS, bir zaman aşımından (genellikle 20–30 saniye) sonra onu .disconnected durumuna geçirir. İzleme için CBPeripheral üzerinde readRSSI kullanın — kullanılamıyorsa, CBError.connectionTimeout koduyla bir hata döndürür. Bağlantı kaybını zamanında tespit etmek için centralManager:didDisconnectPeripheral:error: öğesini de izleyin.
Core Bluetooth iş parçacığı güvenli değildir — tüm CBPeripheral çağrıları aynı kuyruktan (genellikle ana kuyruk veya CBCentralManager başlatılırken belirtilen seri kuyruk) yapılmalıdır. Farklı iş parçacıklarından eşzamanlı çağrılar, yarış koşullarına ve uygulama çökmelerine neden olur. Tüm BLE işlemleri için DispatchQueue(label: “com.app.ble”) ve UI güncellemeleri için DispatchQueue.main.async kullanın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun