【RxSwift】materialize, dematealizeを使ってみた

公開日: : iOSアプリ開発

記事内に広告を含む場合があります。記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。

@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

この記事を書いた人
あきお(@akio0911
派手髪iOSエンジニア。Twitterアカウントは@akio0911。YouTubeチャンネル「あきおチャンネル」にてiOSアプリ開発講座を公開中。著書に「iPhoneアプリ開発レシピ」「cocos2d for iPhoneレッスンノート」など。iOSアプリ開発をテーマとしたオンラインサロン「アプリ道場サロン」を運営。東京・大阪にてアプリ開発講座「アプリクリエイター道場」を主催。

関連記事

この記事が気に入ったら「いいね!」しよう

Twitterで更新情報をゲット!

PAGE TOP ↑