RxSwiftを初めて使う際に、CombineLatestの便利さに驚きを隠せなかったが、それと同時に落とし穴が存在したので、忘れないようにメモする。
CombineLatestとは?
ReactiveXの公式ドキュメントによると、CombineLatestは以下のように説明されている。
when an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function
上記の文章をそのまま訳すと、
「2つのObservableのどちらかがアイテムを発行した場合、指定された関数でそれぞれのObservableが発行した最新のアイテムを結合し、この関数の結果に基づいてアイテムを発行します。」
となります。
具体例
具体例をあげて説明します。
まず、どちらかの値が更新されたときに、監視したいObservableのAとBがあるとします。
private let A = BehaviorRelay<String>(value:"")
private let B = BehaviorRelay<String>(value:"")
Observable.combineLatest(A, B)
.subscribe(onNext: {a, b in
print("a,b:\(a,b)")
})
.dispose(by: disposeBag)
これでAとBのどちらに値が流れてきても、監視をし続けることができます。
例えば、Aだけに値が流れてきたら、ちゃんとprintが呼び出されますし、Bだけがよばれてもしっかりとprintされます。
しかし、ここにおいて落とし穴が存在します。
落とし穴
private let A = BehaviorRelay<String>(value:"")
private let B = BehaviorRelay<String>(value:"")
ここに注意してみてみてください。
どうしてわざわざBehaviorRelayで初期値を持たせているのでしょうか??
理由は単純でCombineLatestを使う際は、初めに監視している値、両方に値が流れてこない と監視を始めないからです。
つまり、一度A,B両方ともに値が流れない限り、CombineLatestは監視を始めません。
CombineLatestはとても便利な関数ですが、この点に注意しましょう。