はじめに
RxSwiftには多くのオペレータが登場し、慣れるまでその理解が大変です。
そこで今回、RxSwift研究読本1と2を読んで登場したオペレータや、そのほか基本的なオペレータを整理してみました。
書籍の中では実装やテスト方法についても書かれているので、詳しくはそちらを読んでみると良いと思います。
オペレータ
正常系
filter
条件に合うもののみにフィルタリングする。
skip
先頭から指定した数だけイベントを無視してスキップする。
take
イベントを最初の指定した数だけに絞り、指定数に達した時点でcompletedになる。
map
新しいObservableインスタンスを返す。
flatMap
mapとの違い、型パラメータとしてObservableConvertibleTypeに準拠している必要があり、その返り値もそれに準拠している必要がある。
flatMapLatest
flatmapと違い、最新でないイベントを破棄する。
zip
複数のObservableを順番に組み合わせる。注意として一方のみの値が変っても更新されず、最新状態ではないことを認識しておく必要がある。
combineLatest
可変長でObservableを引数にとり、最後の引数にresultSelectorをとる。resultSelectorでは、各Observableの値が変わるたびに、その戻り値を次へと流れるObservableを返す。
withLatestFrom
combineLatestと違って、イベントの発行タイミングは最初のObservable の発行タイミング。
エラー系
retry
ストリームからのエラー通知時に、それをオブザーバーに通知せず、自動でストリームを再購読する。
catchError
Observableを返すことで、エラーを書き換えることができる。
エラーに応じて、自由にストリームを返したい場合や何も返したくない場合に使用する。
catchErrorJustReturn
catchErrorJustReturnは、catchErrorのラッパーとなっている。
任意の要素に書き換えたい場合に使用する。
extension ObservableType {
public func catchError(_ handler: @escaping (Swift.Error) throws -> Observable<E>)
-> Observable<E> {
return Catch(source: asObservable(), handler: handler)
}
public func catchErrorJustReturn(_ element: E)
-> Observable<E> {
return Catch(source: asObservable(), handler: { _ in Observable.just(element) })
}
}
ストリームの分岐
materialize
ObservableとしてたonNextイベントとonErrorイベントを一つの、Observable>として変換する。
2個のストリームを作成することで、正常系と異常系に関して、別々に購読できるようになる。
let observable = Observable<String>.create { observer in
observer.onNext("A")
observer.onError(TestError.test)
return Disposables.create()
}
_ = observable.materialize()
.subscribe(onNext: { (event: Event<String>) in
switch event {
case .next(let value):
print("value: \(value)")
case .error(let error):
print("error: \(error)")
case .completed:
break
}
}, onError: {
print("onError, onError: \($0)")
}, onCompleted: {
print("onCompleted:")
})
ただ正常系と異常系の分岐を、毎回書くのは面倒なので、後述するcompactMapを使用したextensionを作成すると良い。
compactMap
RxSift5.0で追加。
filterおよびmapメソッドをcompactMapメソッドでの書き換えでき、compactMapオペレータは、要素のnilをfilterしてmapしたストリームに変換してくれる。
extension ObservableType where Element: EventConvertible {
public func elements() -> Observable<Element.Element> {
return filter { $0.event.element != nil }
.map { $0.event.element! }
}
public func errors() -> Observable<Swift.Error> {
return filter { $0.event.error != nil }
.map { $0.event.error! }
}
}
extension ObservableType where Element: EventConvertible {
public func elements() -> Observable<Element.Element> {
return compactMap { $0.event.element }
}
public func errors() -> Observable<Swift.Error> {
return compactMap { $0.event.error }
}
}
Single等では、materializeオペレータがそのままは使えない
ObservableTypeに準拠していないSingleなどの、PrimitiveSequence型は"そのまま"ではmaterializeオペレータを使用できない。
- PrimitiveSequence型
-
Single
- 成功か失敗のみ送信できる
- 完了は送信できない
- いずれかのイベントを送信すると、disposeされる
-
Maybe
- 成功、失敗、完了を送信することができる
- いずれかのイベントを送信すると、disposeされる。
-
Completable
- 完了か失敗のみ送信できる。
- 成功は送信できない
- いずれかのイベントを送信すると、disposeされる。
-
PrimitiveSequenceのStructとして、Single、Maybe、Completableは実装されている。
ジェネリクスでTraitsを切り替えることで、それらTraits(Single、Maybe、Completable)の振る舞いをするようになっている。
これらのTraitsはストリームを内部に保持したラッパーのため、materializeオペレータを使用できない。
そのためRxSwiftでは、PrimitiveSequenceのasObservable()で取り出せるように実装されている。
extension PrimitiveSequence: ObservableConvertibleType {
/// Type of elements in sequence.
public typealias E = Element
/// Converts `self` to `Observable` sequence.
///
/// - returns: Observable sequence that represents `self`.
public func asObservable() -> Observable<E> {
return source
}
}
参考
RxSwift研究読本1 入門編
RxSwift研究読本2 エラーハンドリング編
https://qiita.com/k5n/items/e80ab6bff4bbb170122d
https://qiita.com/moaible/items/de94c574b25ea4f0ef17
https://qiita.com/k5n/items/17f845a75cce6b737d1e
https://qiita.com/crea/items/d46360e1eac709d6a632
https://qiita.com/bouzuya/items/d019c3eae5db19e395cd