在RxSwift中重新启动可观察间隔的正确方法

Mac*_*iak 2 swift rx-swift

在我的OS X状态栏应用程序中,我正在使用interval函数定期调用外部api并显示结果:

Observable<Int>
    .interval(120.0, scheduler: MainScheduler.instance)
    .startWith(-1) // to start immediately
    .flatMapLatest(makeRequest) // makeRequest is (dummy: Int) -> Observable<SummaryResponse?>
    .subscribeNext(setSummary)
    .addDisposableTo(disposeBag)
Run Code Online (Sandbox Code Playgroud)

但是,如果用户在此期间更改了首选项,我希望"重新启动"此时间间隔并立即进行新呼叫以反映更改(无需等待下一次调用).

最好的方法是什么?

  1. 将observable存储为属性并将其设置为nil或调用.dispose()它(或两者)并创建一个新的可观察对象?
  2. 设置disposeBagnil创建一个新的观察到的?
  3. 还有其他方法吗?

sol*_*ell 6

你在寻找什么merge.你有两个Observables,其中一个是一个interval,另一个代表偏好变化.你希望merge那些Observable与两者中的元素合二为一的,就在他们来的时候.

这看起来像这样:

// this should really come from somewhere else in your app
let preferencesChanged = PublishSubject<Void>()

// the `map` is so that the element type goes from `Int` to `Void`
// since the `merge` requires that the element types match
let timer = Observable<Int>.timer(0, period: 3, scheduler: MainScheduler.instance).map { _ in () }

Observable.of(timer, preferencesChanged)
    .merge()
    .flatMapLatest(makeRequest)
    .subscribeNext(setSummary)
    .addDisposableTo(disposeBag)
Run Code Online (Sandbox Code Playgroud)

还要注意我是如何使用timerinterval,因为它允许我们指定第一次点火的时间,以及后续点火的时间.那样,你不需要startWith.但是,这两种方式都有效.这是一个偏好问题.

还有一点需要注意.这是你的问题的范围之外(也许你保持它的简单的问题的缘故),但代替subscribeNext(setSummary),你应该考虑保持结果作为可观察到的,而是bindTodrive用户界面或DB(或任何"摘要"是).