SwiftUI Combine:发送前加索引/UUID解决List的RandomAccessCollection错误
解决Combine发送CBPeripheral时的索引/UUID添加及List集合适配问题
一、为CBPeripheral添加UUID或索引
直接发送CBPeripheral无法携带额外标识,你可以通过包装结构体实现,同时让结构体遵循Identifiable协议,方便后续List组件使用:
方案1:使用UUID作为唯一标识
// 定义包装结构体 struct IdentifiedPeripheral: Identifiable { let id: UUID let peripheral: CBPeripheral let rssi: NSNumber // 可按需加入广告数据等其他信息 } // 修改Subject类型 var peripheralSubject: PassthroughSubject<IdentifiedPeripheral, Never> = .init() // 发现外设时发送包装后的对象 func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { let wrappedPeripheral = IdentifiedPeripheral( id: UUID(), peripheral: peripheral, rssi: RSSI ) peripheralSubject.send(wrappedPeripheral) }
方案2:使用自增索引作为标识
如果需要按发现顺序生成索引,可维护一个计数器:
private var peripheralIndex = 0 struct IndexedPeripheral: Identifiable { let id: Int let peripheral: CBPeripheral let rssi: NSNumber } var peripheralSubject: PassthroughSubject<IndexedPeripheral, Never> = .init() func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { let wrappedPeripheral = IndexedPeripheral( id: peripheralIndex, peripheral: peripheral, rssi: RSSI ) peripheralIndex += 1 peripheralSubject.send(wrappedPeripheral) }
二、解决List的RandomAccessCollection错误
List要求数据源遵循RandomAccessCollection协议,同时元素需具备唯一标识。你需要将Subject的输出收集到数组中,再绑定给List:
// 定义用于展示的数组 @Published var discoveredPeripherals: [IdentifiedPeripheral] = [] var cancellables = Set<AnyCancellable>() // 在初始化方法中订阅Subject,将数据存入数组 init() { peripheralSubject .receive(on: DispatchQueue.main) // 切换到主线程更新UI .sink { [weak self] wrappedPeripheral in self?.discoveredPeripherals.append(wrappedPeripheral) } .store(in: &cancellables) } // 界面中使用List List(discoveredPeripherals) { item in VStack(alignment: .leading) { Text(item.peripheral.name ?? "未命名外设") Text("RSSI: \(item.rssi)") .font(.caption) .foregroundColor(.secondary) } }
内容的提问来源于stack exchange,提问作者stoney
相关产品推荐
相关产品推荐

