iOS 17.x下swift_isUniquelyReferenced_nonNull_native引发BLE流程崩溃求助
问题概述
- 仅在iOS 17.x版本中,App执行「BLE连接外设 → WiFi扫描 → 通过BLE连接WiFi」流程时,出现随机但系统性的崩溃。
相关BLE交互代码示例
// BLE外设连接逻辑 func connectToPeripheral(_ peripheral: CBPeripheral) { peripheral.delegate = self centralManager.connect(peripheral, options: [CBConnectPeripheralOptionNotifyOnDisconnectionKey: true]) } // WiFi扫描触发 func startWiFiScan() { let scanner = NEHotspotConfigurationManager.shared scanner.getScanResults { results, error in if let error = error { print("WiFi扫描失败: \(error.localizedDescription)") return } // 处理扫描结果并通过BLE发送给外设 self.sendWiFiInfoViaBLE(results) } } // BLE发送WiFi信息 func sendWiFiInfoViaBLE(_ results: [NEHotspotNetwork]?) { guard let peripheral = connectedPeripheral, let service = peripheral.services?.first(where: { $0.uuid == WiFiServiceUUID }), let characteristic = service.characteristics?.first(where: { $0.uuid == WiFiDataCharacteristicUUID }) else { return } let data = // 转换WiFi信息为Data peripheral.writeValue(data, for: characteristic, type: .withResponse) }
Crashlytics崩溃堆栈
Thread 0 Crashed:
0 CoreBluetooth 0x1b8f37d60 0x1b8ee6000 + 339296
1 CoreBluetooth 0x1b8f37a1c 0x1b8ee6000 + 338460
2 CoreBluetooth 0x1b8f3778c 0x1b8ee6000 + 337804
3 CoreBluetooth 0x1b8f1f8dc 0x1b8ee6000 + 235740
4 CoreBluetooth 0x1b8f1f664 0x1b8ee6000 + 235108
5 libdispatch.dylib 0x1f0c5a9a8 _dispatch_call_block_and_release + 32
6 libdispatch.dylib 0x1f0c5c524 _dispatch_client_callout + 20
7 libdispatch.dylib 0x1f0c67b58 _dispatch_main_queue_drain + 928
8 libdispatch.dylib 0x1f0c67770 _dispatch_main_queue_callback_4CF + 44
9 CoreFoundation 0x1f101f308 CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 16
10 CoreFoundation 0x1f1019eec __CFRunLoopRun + 1996
11 CoreFoundation 0x1f101920c CFRunLoopRunSpecific + 608
12 GraphicsServices 0x239777734 GSEventRunModal + 164
13 UIKitCore 0x1f3477fe8 -[UIApplication _run] + 888
14 UIKitCore 0x1f347cb9c UIApplicationMain + 340
15 MyApp 0x102345678 main + 60 (main.m:14)
16 dyld 0x1f0a5fdec start + 2220
问题分析与解决方案
1. 线程同步问题
iOS 17中CoreBluetooth回调与NEHotspotConfigurationManager扫描回调可能在不同线程执行,未同步会导致BLE资源野访问。
- 解决措施:用专用串行队列统一处理所有BLE操作:
private let bleQueue = DispatchQueue(label: "com.myapp.ble.queue") // 修改连接逻辑 func connectToPeripheral(_ peripheral: CBPeripheral) { bleQueue.async { peripheral.delegate = self self.centralManager.connect(peripheral, options: [CBConnectPeripheralOptionNotifyOnDisconnectionKey: true]) } } // WiFi扫描结果切换到BLE队列处理 func startWiFiScan() { let scanner = NEHotspotConfigurationManager.shared scanner.getScanResults { [weak self] results, error in guard let self = self else { return } if let error = error { print("WiFi扫描失败: \(error.localizedDescription)") return } self.bleQueue.async { self.sendWiFiInfoViaBLE(results) } } }
2. 流程时序冲突
WiFi扫描会占用系统无线资源,若在BLE连接未完全建立时启动扫描,易触发框架崩溃。
- 解决措施:在BLE连接确认回调后再启动WiFi扫描:
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("BLE外设已连接") // 延迟100ms确保连接状态稳定 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.startWiFiScan() } }
3. 代理对象生命周期问题
若CBPeripheral或CBCentralManager的代理被提前释放,框架回调时会访问野指针。
- 解决措施:强引用连接的外设直到断开:
class BLEManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { private var centralManager: CBCentralManager! private var connectedPeripheral: CBPeripheral? // 强引用外设 override init() { super.init() centralManager = CBCentralManager(delegate: self, queue: bleQueue) } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { connectedPeripheral = nil // 断开后释放引用 } }
4. iOS 17底层bug规避
部分开发者反馈iOS 17.x存在CoreBluetooth与Network框架交互的底层bug,可临时取消BLE通知再扫描:
func startWiFiScan() { // 临时取消BLE特征值通知 if let characteristic = connectedCharacteristic { connectedPeripheral?.setNotifyValue(false, for: characteristic) } let scanner = NEHotspotConfigurationManager.shared scanner.getScanResults { [weak self] results, error in guard let self = self else { return } // 扫描完成后重新订阅通知 if let characteristic = self.connectedCharacteristic { self.connectedPeripheral?.setNotifyValue(true, for: characteristic) } // 后续处理逻辑 } }
验证建议
- 在iOS 17.0-17.4各版本测试流程稳定性
- 开启Xcode的
Zombie Objects检测定位野指针 - 使用Instruments的
Thread Sanitizer检测线程竞争
内容的提问来源于stack exchange,提问作者Iheb Sahloul

