【RxSwift】materialize, dematealizeを使ってみた
記事内に広告を含む場合があります。記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
@toshi0383さんに教えていただいた、RxSwiftのmaterializeを使ってみました。
materializeとは何か?
materializeを使うと、Observable<T>をObservable<Event<T>>に変換することができます。
コードと実行結果を見たほうが理解しやすいかもしれません。
materializeを使ってみる
ではさっそくmaterializeを使ってみましょう。nextとcompletedを流してみます。
let subject = PublishSubject<Int>() subject .materialize() .subscribe(onNext: { (event: Event<Int>) in print("onNext", event) }, onError: { error in print("onError", error) }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed") }).disposed(by: disposeBag) subject.onNext(100) subject.onCompleted()
以下、実行結果です。流したnextとcompletedがnextにラップされていることが分かります。また、ラップされていないcompletedも流れています。これについては後述します。
onNext next(100)
onNext completed
onCompleted
onDisposed
次はnextとerrorを流してみます。
let subject = PublishSubject<Int>() subject .materialize() .subscribe(onNext: { (event: Event<Int>) in print("onNext", event) }, onError: { error in print("onError", error) }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed") }).disposed(by: disposeBag) subject.onNext(100) subject.onError(Error())
以下、実行結果です。流したnextとerrorがnextにラップされていることが分かります。また、先ほどと同様にラップされていないcompletedも流れています。
onNext next(100)
onNext error(Error())
onCompleted
onDisposed
dematealizeを使ってみる
materializeの反対の操作、つまりObservable<Event<T>>をObservable<T>に変換してくれるdematealizeというメソッドも用意されています。
let subject = PublishSubject<Int>() subject .materialize() .dematerialize() .subscribe(onNext: { (num: Int) in print("onNext", num) }, onError: { error in print("onError", error) }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed") }).disposed(by: disposeBag) subject.onNext(100) subject.onError(Error())
以下、実行結果です。materializeの後にdematerializeを呼ぶことで、元々のストリームに戻っていることが分かります。
onNext 100
onError Error()
onDisposed
Eventでラップされていないcompletedも流れる
materializeはcompletedをnextでラップするだけでなく、nextでラップされていない普通のcompletedも流します。
以下の記事で示されている図を見ると理解しやすいと思います。
ReactiveX – Materialize & Dematerialize operators
また、以下のページでmaterializeのコードを読むと、errorまたはcompletedが流れてきた時は、nextでラップして流した後にnextでラップされていないcompletedを流していることが分かります。
RxSwift/Materialize.swift at master · ReactiveX/RxSwift
なお、materializeの実装で使っているisStopEventのコードは以下のページで確認できます。errorまたはcompletedの時にtrueを返しています。
RxSwift/Event.swift at master · ReactiveX/RxSwift
まずは普通にmaterializeを使ってみましょう。
let subject = PublishSubject<Int>() subject .materialize() .subscribe(onNext: { (event: Event<Int>) in print("onNext", event) }, onError: { error in print("onError", error) }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed") }).disposed(by: disposeBag) subject.onNext(100) subject.onCompleted()
以下、実行結果です。nextでラップされたnext(100)と、nextでラップされたcompletedが流れていることが分かります。
onNext next(100)
onNext completed
onCompleted
onDisposed
次に、filterですべてのnextを除去してみましょう。
let subject = PublishSubject<Int>() subject .materialize() .filter{ _ in false } .subscribe(onNext: { (event: Event<Int>) in print("onNext", event) }, onError: { error in print("onError", error) }, onCompleted: { print("onCompleted") }, onDisposed: { print("onDisposed") }).disposed(by: disposeBag) subject.onNext(100) subject.onCompleted()
以下、実行結果です。先ほどのnextでラップされたnext(100)と、nextでラップされたcompletedは除去されましたが、nextでラップされていないcompletedは先ほどと変わらず流れています。
onCompleted
onDisposed
関連記事
この記事が気に入ったら「いいね!」しよう
Twitterで更新情報をゲット!