【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で更新情報をゲット!



