首页 > 解决方案 > 每 60 秒观察一次 observable,并与它在 RxSwift 中的先前值进行比较

问题描述

我想做的是:

发生的事情是$0我总是得到第一个发出的事件,它不是每 60 秒更新一次。$1 有最新的发射事件。

这是代码:

Observable<Int>.timer(.seconds(0), period: .seconds(60), scheduler: MainScheduler.instance)
            .withLatestFrom(location)
            .distinctUntilChanged { $0.distance(from: $1).magnitude < 10.0 }
            .subscribe(onNext: { (location) in
                print(location)
            })
            .disposed(by: disposeBag)

标签: iosswiftreactive-programmingcore-locationrx-swift

解决方案


您要求的是在设备超过一定速度时发出一个值,该值实际上是在位置对象中提供的。就用它吧。

extension CLLocationManager {
    func goingFast(threshold: CLLocationSpeed) -> Observable<CLLocation> {
        return rx.didUpdateLocations
            .compactMap { $0.last }
            .filter { $0.speed > threshold }
    }
}

有了上述内容,如果您想知道设备在过去 60 秒内的任何时间点是否超过 10 m/s,您可以使用sampleAlexander 在评论中提到的:

let manager = CLLocationManager()
let fast = manager.goingFast(threshold: 0.167)
    .sample(Observable<Int>.interval(.seconds(60), scheduler: MainScheduler.instance))

也就是说,作为跟踪幅度增加的一般情况,您需要使用scan运算符。

extension CLLocationManager {
    func example(period: RxTimeInterval, threshold: Double, scheduler: SchedulerType) -> Observable<CLLocation> {
        return rx.didUpdateLocations
            .compactMap { $0.last }
            .sample(Observable<Int>.interval(period, scheduler: scheduler))
            .scan((CLLocation?.none, false)) { last, current in
                if (last.0?.distance(from: current).magnitude ?? 0) < threshold {
                    return (current, false)
                }
                else {
                    return (current, true)
                }
            }
            .filter { $0.1 }
            .compactMap { $0.0 }
    }
}

推荐阅读