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

时间:2016-05-25 20:04:16

标签: 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)

但是,如果用户在此期间更改了首选项,我想“重新启动”此时间间隔并立即拨打新电话以反映更改(无需等待下一次调用)。

最好的方法是什么?

  1. 将observable存储为属性并将其设置为nil或在其上调用.dispose()(或两者)并创建一个新的observable?
  2. disposeBag设置为nil并创建一个新的observable?
  3. 还有其他方式吗?

1 个答案:

答案 0 :(得分:5)

您正在寻找的是merge。您有两个Observable,其中一个是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)

看起来像这样:

timer

另请注意我如何使用interval代替startWith,因为它允许我们指定第一次开火的时间,以及后续开火的时间。这样,您就不需要subscribeNext(setSummary)。但是,这两种方式都有效。这是一个偏好的问题。

还有一点需要注意。这超出了你的问题的范围(也许你为了问题而保持简单)但是你应该考虑将结果保持为Observable而不是bindTodrive而不是DateTime。 {1}}用户界面或数据库(或其他任何&#34;摘要&#34;)。