一旦找到匹配项,如何停止 RxSwift ble 扫描器?
How do I stop RxSwift ble scanner once it has found a match?
我有一个 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 { [=10=] == .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: { [=11=].identifier.uuidString == door.dPeripheralId }) }
}
}
并且在 view
扫描完成后我想连接:
private func scanAndConnect(data: LocalDoorCoreDataObject) {
viewModel.scanRelay().subscribe(
onNext: {
print("SCANNED NAME", [=12=].first?.dName)},
onCompleted: {
print("COMPLETED SCAN")
self.connectToFilteredPeripheral(localDoor: data)
}).disposed(by: disposeBag)
}
它永远不会到达 onCompleted
,因为即使在找到 filtered
core data
匹配后,它也会一直扫描下去。在 Apple 的框架 coreBluetooth
中,我可以在找到我想要的内容后简单地调用 manager.stopScan()
,但是 Rx
对应的框架似乎不可用。它如何适用于 RxSwift
您可以创建一个新的 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 will make sure that only lists that contain the device you're looking for are passed on and the take(1)
operator 将获取第一个发出的值并立即完成。
deferred
调用确保第一行中执行的获取请求不会在您调用 scanAndFilter()
时执行,而只会在有人实际订阅生成的 Observable 时执行。
如果只想让一个事件退出过滤算子,那么就用.take(1)
。 Observable 将在发出单个值后关闭。如果BLE函数写对了,Disposable处理时会调用stopScan()
我不知道为什么另一个答案说“始终确保将 return Observables 的所有函数包装到 .deferred
中。自 2015 年以来我一直在使用 RxSwift,并且我已经只需要延迟一次。当然不是每次我调用 returned 一个 Observable 的函数时。
我有一个 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 { [=10=] == .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: { [=11=].identifier.uuidString == door.dPeripheralId }) }
}
}
并且在 view
扫描完成后我想连接:
private func scanAndConnect(data: LocalDoorCoreDataObject) {
viewModel.scanRelay().subscribe(
onNext: {
print("SCANNED NAME", [=12=].first?.dName)},
onCompleted: {
print("COMPLETED SCAN")
self.connectToFilteredPeripheral(localDoor: data)
}).disposed(by: disposeBag)
}
它永远不会到达 onCompleted
,因为即使在找到 filtered
core data
匹配后,它也会一直扫描下去。在 Apple 的框架 coreBluetooth
中,我可以在找到我想要的内容后简单地调用 manager.stopScan()
,但是 Rx
对应的框架似乎不可用。它如何适用于 RxSwift
您可以创建一个新的 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 will make sure that only lists that contain the device you're looking for are passed on and the take(1)
operator 将获取第一个发出的值并立即完成。
deferred
调用确保第一行中执行的获取请求不会在您调用 scanAndFilter()
时执行,而只会在有人实际订阅生成的 Observable 时执行。
如果只想让一个事件退出过滤算子,那么就用.take(1)
。 Observable 将在发出单个值后关闭。如果BLE函数写对了,Disposable处理时会调用stopScan()
我不知道为什么另一个答案说“始终确保将 return Observables 的所有函数包装到 .deferred
中。自 2015 年以来我一直在使用 RxSwift,并且我已经只需要延迟一次。当然不是每次我调用 returned 一个 Observable 的函数时。