我有一个工作正常且外观如下的ble
扫描仪:
func scan(serviceId: String) -> Observable<[BleHandler.BlePeripheral]> {
knownDevices = []
return waitForBluetooth()
.flatMap { _ in self.scanForPeripheral(serviceId: serviceId) }
.map { _ in self.knownDevices }
}
private func waitForBluetooth() -> Observable<BluetoothState> {
return self.manager
.observeState()
.startWith(self.manager.state)
.filter { $0 == .poweredOn }
.take(1)
}
然后在viewModel
class
中过滤来自core data
的匹配项:
func scanAndFilter() -> Observable<[LocalDoorCoreDataObject]> {
let persistingDoors: [LocalDoorCoreDataObject] = coreDataHandler.fetchAll(fetchRequest: NSFetchRequest<LocalDoorCoreDataObject>(entityName: "LocalDoorCoreDataObject"))
return communicationService
.scanForDevices(register: false)
.map{ peripherals in
print("🐶 THIS WILL GO ON FOR ETERNITY", peripherals.count)
self.knownDevices = peripherals
return persistingDoors
.filter { door in peripherals.contains(where: { $0.identifier.uuidString == door.dPeripheralId }) }
}
}
并且在view
中,我想在扫描完成后连接:
private func scanAndConnect(data: LocalDoorCoreDataObject) {
viewModel.scanRelay().subscribe(
onNext: {
print("🐶SCANNED NAME", $0.first?.dName)},
onCompleted: {
print("🐶COMPLETED SCAN")
self.connectToFilteredPeripheral(localDoor: data)
}).disposed(by: disposeBag)
}
它永远不会到达onCompleted
,因为即使找到并与filtered
匹配core data
,它也只会扫描永恒。在Apple的框架coreBluetooth
中,我可以在找到我想要的内容后简单地调用manager.stopScan()
,但是Rx
对应对象上似乎没有这个功能。 RxSwift
首先,始终确保将所有返回Observable的函数包装到Observable.deferred
中(更多信息here)。
您可以创建一个新的Observable来查找设备,然后在找到要查找的设备后立即完成。类似于:
func scanAndFilter() -> Observable<[LocalDoorCoreDataObject]> {
return Observable.deferred { in
let persistingDoors: [LocalDoorCoreDataObject] = coreDataHandler.fetchAll(fetchRequest: NSFetchRequest<LocalDoorCoreDataObject>(entityName: "LocalDoorCoreDataObject"))
return communicationService
.scanForDevices(register: false)
.filter { /* verify if the device(s) you're looking for is/are in this list */ }
.take(1)
}
}
filter
operator将确保仅传递包含您要查找的设备的列表,并且filter
将采用第一个发出的值并立即完成。
如果只希望一个事件退出过滤器运算符,则只需使用take(1)
operator。 Observable发出单个值后将关闭。如果BLE功能编写正确,则处置Disposable时它将调用take(1)
。
我不知道为什么另一个答案说“总是确保将所有返回Observables的函数包装到.take(1)
中。自2015年以来我一直在使用RxSwift,而我只需要推迟一次。当然不是每个我调用了一个返回Observable的函数。