RxSwift入門 Observableの概要 まとめ

入門

まずは上の記事でリアクティブプログラミングのノリを理解します。特に6pのマーブルダイヤグラムの図が理解に役立ちます。下の記事は実際のコードを交えた解説です。具体的にどのような実装を行えば良いのかがわかります。

Rxができることとそのメリット

Rxを使いこなせればありとあらゆるものをストリームとして扱うことが可能です

everything is stream

例えばボタンをタップされた時の挙動はこう書けます。(以下のコードは厳密にはRxSwiftではなくRxCocoaというUIKitをObservableとして扱うことのできるライブラリを用いています。)

import RxCocoa
import RxSwift

weak var button: UIButton!

~~~~~~~~~~~~~~~~~~

override func viewDidLoad(){
  button.rx.tap.subscribe(onNext: { _ in
    print("buttonがtapされたよー")  
  }).disposed(by: DisposeBag())
}

例えばデータのbindや、面倒だった非同期処理を簡単に書けるけるのがメリットです。若干学習コストは高いかなと思いますが、マスターできれば文字通りなんでもできます。

Rxで登場する基本概念 2種

Observable

名前だけでも覚えて帰ってください!!Observableはストリームを流し、そのストーリムをsubscribe(購読)することが可能になります。

言い換えると、何かが起こった時の挙動をクロージャの中に記述しておけば何もせんでも勝手に呼んでくれるということです。下のコードは新卒エンジニアの開発日記さんの記事から引用したものになります。趣旨とは外れますが、中の人とは実は学生時代の知り合いだったりします。笑

import RxSwift
import RxCococa

let observableContentOffset = tableView.rx.contentOffset

observableContentOffset
    .subscribe(onNext: { _ in
        print("next")      //スクロールするたびに呼ばれる
    }, onError: { _ in
        print("error")
    }, onCompleted: { _ in 
        print("completed")
    }).disposed(by: DisposeBag())

Disposable

}.disposed(by: DisposeBag())

について疑問を持った方も多いと思います。これについて説明します。こう書くことによって購読を解除できます。購読し続けるとその分メモリを圧迫し、アプリのパフォーマンスに影響するので基本的にはメソッドが走った最後に購読を解除します。今まで特に理解せずにこのメソッドを使っていましたが、オブザーバーパターンから始めるRxSwift入門 から引用するとどうやら

管理下にある全ての Disposable の dispose が呼び出されます。

ということのようです。ちなみにDisposableを直訳すると「使い捨て」になります。何と無くイメージできるかなと思います。

様々なObservable

一口にObservableと言っても様々なTraitが用意されています。以下にざっくりとまとめます。

Subject

SubjectはObserver(購読者)から購読されるだけでなく、外部に対し任意のストリームイベントを発行できるObservableです。

Relay

onNextしか流さないSubject。uiのbindなど成功が保証されている場合はsubjectよりもこちらを使うのがベターです。 BehaviorRelayとPublishRelayについてまとめてみた

single

一回しか流れない enter link description here

driverとsignal

サブスクライブされる時にDriverは一回replayしますがSignalはreplayしないです。 ちなみにRxSwift独自で提供されていたVariableはRxSwift4で廃止になりました。代わりにはBehaviorRelyを使います。

補足 Variableについて

RxSwift独自に提供されていたTraitであるVariableは非推奨(deprecated)になりました。ViewModelのプロパティとして使っている方が多くいらっしゃるかと思いますが、代わりにBehaviorSubject、もしくはBehaviorRelayを使うと良いかと思います。