はじめに
そろそろ勉強しなきゃという思いとRxSwiftを触ってみたいなという思いがぶつかってQiita書こうと思いました。
そもそもRxって?
Reactive Extensionsの略称でリアクティブプログラミングを実現するための
設計パターン及び、ライブラリを指します。
元々は、マイクロソフトが自社製品に組み込んでいる.NETフレームワークに向けて開発した.NET用のライブラリ(Rx.NET)でしたが、あまりにも強力な技法だったので色んな言語に波及していきました。
それがSwiftにも波及してきてRxSwiftが開発されました。
リアクティブプログラミングとは
難しく感じますが、エクセルやスプレッドシートをイメージすると分かりやすいです。
例えば、このように
A1=1
B1=2
の値を入力してC1に=A1+B1という関係を入力します。
すると瞬時に計算が走って値が出力されました。
B1の値を変えたとしても、A1の値を変えたとしてもC1に計算の答えが瞬時に出力されます。
このような動きが正にリアクティブプログラミングと言われています。
リアクティブプログラミングは時間軸を重視したプログラミング方法となっており
プログラム内での値の変化を時間軸で捉え、値が変わったというイベントによって処理を行います。
先ほどのエクセルやスプレッドシートの例を図にするとこんな感じ↓
左から右に時間が流れ、そこにイベントが流れてきます。
ここではAもしくはBの値が変化したというイベントが流れます。
そして、イベントが発生したらA+B=Cという処理が走っています。
上記の図は、正式名称がありマーブルダイアグラムと呼ばれています。
下記のサイトに色んなオペレーター(演算)によるマーブルダイアグラムの図が
載っていますので見てみて下さい↓
RxMarbles
このようにマーブルダイアグラムでは時間順に並んだ進行中のイベントが流れており
これらをストリームと呼びます。
Observer(オブザーバー)パターン
ObserverパターンはRxの根幹となる考え方です。
この考え方には観測対象と観測者の2つの役割が存在しています。
観測対象を観測者が観測していて、観測対象の何らかのイベントを観測者が確認したら特定のアクションを起こすというのが基本の考え方となっています。
ただ実際に実装する際は観測対象に観測者を登録して、観測対象でイベントが発生したら観測者に知らせて特定のアクションを起こすといった流れになります。
ここでいうイベントは、ボタンがタップされた・文字が入力された・APIから値が取得できた等、プログラム内におけるオブジェクトの状態変化すべてを指します。
ObservableとObserver
Observerパターンでは次の2つのクラスでストリームを扱います。
・Observable: ストリームを表現するクラス
・Observer: Observableからストリームを受け取るクラス
subscribe
Observableはsubscribeメソッドを持っています。
これは何なのかというと、通知先を登録するメソッドです。
つまり、Observableに対してObserverを登録するメソッドですね。
※Observableを監視することをsubscribeとも呼んでいます。
先ほどの図で表すとこんな感じ↓
Observableが通知するイベント
Observableが通知するイベントは3種類あり、enumで定義されています。
これらのイベントをObserverが受け取ります。
public enum Event<Element> {
// 通常のイベントを通知、値を渡すことができる
// 複数回送れる
case next(Element)
// エラーの発生を通知
// 発生後はイベントが一切発生しない
case error(Error)
// 完了を通知、値を渡せない
// 発生後はイベントが一切発生しない
case completed
}
図に表すとこんな感じ↓
実際にコードで書くとこのようになります↓
let observable = textField.rx.text.orEmpty.asObservable()
observable.subscribe(onNext: { text in
print(text)
}, onError: { error in
print(error)
}, onCompleted: { _ in
print("完了")
})
コードを見てみると流れてきたイベントに対する処理をObservableに登録しているという見方もできます。
そして、注意して欲しいのが一度、onCompletedやonErrorが発生すると
それ以降はonNextを呼ぶことが出来ません。
Disposable
Observableをsubscribeすると、Disposableというものを返します。
これは、subscribeしたObservableをunsubscribeするための仕組みで
無視するとsubscribeした処理が永遠に解放されずにメモリリークに繋がる恐れがあります。
その解決策としてDisposeBagというものがあります。
これは内部でDisposableを貯めておいて
自身が解放された時に保持しているDisposableを廃棄してくれます。
Observableはdisposeメソッドを持っており、呼び出してDisposeBagを代入する事によって
subscribe時に返されるDisposableをDisposeBagに貯める処理を定義しています。
public func disposed(by bag: DisposeBag) {
// selfがDisposableのこと
bag.insert(self)
}
実際に先ほどのコードで使用した場合↓
// DisposeBagを初期化する
let dispoceBag = DisposeBag()
let observable = textField.rx.text.orEmpty.asObservable()
observable.subscribe(onNext: { text in
print(text)
}, onError: { error in
print(error)
}, onCompleted: { _ in
print("完了")
// 最後にメソッドを呼ぶ
}).disposed(by: dispoceBag)
循環参照に注意する
subscribe時の処理の中のクロージャはselfを強参照すると
解放されなくなってしまいます。
なのでselfを弱参照しましょう。
let dispoceBag = DisposeBag()
let observable = textField.rx.text.orEmpty.asObservable()
// weakキーワードでselfを弱参照にする
observable.subscribe(onNext: {[weak self] text in
print(text)
}, onError: { error in
print(error)
}, onCompleted: { _ in
print("完了")
}).disposed(by: dispoceBag)
おわりに
キリがいいのでここで終わります。次回もいつか書こうと思います。
間違っている部分や説明が足りない部分はコメントして教えて下さると有り難いです。
参考記事
【Swift】RxSwift勉強してみたPart4
【RxSwift】Singleton で DisposeBag を使うことの考察
RxSwiftについてようやく理解できてきたのでまとめることにした(1)
SwiftでReactive Programming - Qiita
Rx入門 (2) - オブザーバーパターン - xin9le.net
RxSwiftでiOSアプリ開発~リアクティブプログラミングを導入する - CodeZine






