You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CoreBluetooth为何会显示蓝牙已关闭的外设?

问题分析与解决

可能的原因

  • 系统蓝牙栈缓存残留:iOS/macOS的蓝牙系统会保留近期发现的外设信息,即便设备蓝牙已关闭,短时间内仍可能返回缓存的外设数据,尤其是刚关闭蓝牙的场景下。
  • CBPeripheral对象判断逻辑缺陷:你当前用peripherals.contains(peripheral)判断是否重复添加,但该判断基于对象引用而非设备唯一标识(如UUID)。系统可能为同一外设生成多个CBPeripheral实例,导致重复添加;或是之前缓存的实例仍存于数组中,即便设备已离线。
  • 设备蓝牙未真正完全关闭:部分设备的蓝牙关闭存在延迟,或是处于待机间歇广播的“伪关闭”状态,仍会被扫描到。

解决办法

  1. 基于UUID去重:改用外设的identifier(唯一稳定UUID)区分设备,替代对象引用判断,修改代码如下:
var peripheralUUIDs = [UUID]()
var peripherals = [CBPeripheral]()

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    guard let name = peripheral.name, !name.isEmpty else { return }
    if !peripheralUUIDs.contains(peripheral.identifier) {
        peripheralUUIDs.append(peripheral.identifier)
        peripherals.append(peripheral)
        table.reloadData()
    }
}
  1. 扫描前清空旧数据:每次启动扫描前,清空存储外设和UUID的数组,避免残留历史缓存:
func startScan() {
    peripherals.removeAll()
    peripheralUUIDs.removeAll()
    centralManager.scanForPeripherals(withServices: nil)
}
  1. 监听外设断开事件:实现断开代理方法,实时移除离线设备:
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
    if let index = peripherals.firstIndex(where: { $0.identifier == peripheral.identifier }) {
        peripherals.remove(at: index)
        peripheralUUIDs.remove(at: index)
        table.reloadData()
    }
}
  1. 过滤异常RSSI:若RSSI值远低于正常范围(如小于-100),判定为缓存数据直接忽略:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    guard let name = peripheral.name, !name.isEmpty, RSSI.intValue > -100 else { return }
    // 后续去重逻辑...
}

内容的提问来源于stack exchange,提问作者stackich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 04:35:29