Open12

RxSwift × MVVM

せーたろせーたろ

ViewControllerの役割

  1. Storyboard の UI コンポーネントをつなぐ
  2. ViewModel を初期化する
  3. ViewModel の出力と UI コンポーネントをバインドする
  4. その他の処理 (例)画面上のタップを検知し入力時のソフトウェアキーボードを閉じる
せーたろせーたろ

ViewModel の役割

  1. API 用のロジックなどをイニシャライザで外部から用意できるようにする
  2. イニシャライザで受け取った Observable を処理して出力に変換

ViewModel のイニシャライザで入力されたストリームは、出力のストリームに変換される→出力はストリームとして読み取られる

せーたろせーたろ

継承による disposeBag の保持

disposeBag はまとめて Observable を処分してくれる
disposeBag に Observable を持たせ、その disposeBag を破棄することで Observable をまとめて破棄できる

せーたろせーたろ

任意のタイミングでの dispose

disposeBag を使って ViewController の破棄と一緒に Observable をまとめて破棄するのが一般的
任意のタイミングで Observable を 破棄することもできる
subscribe メソッドの戻り値 Disposable インスタンスに対して dispose() メソッドを呼び出す方法がある
subscribe メソッドでは dispose されたことを購読でき、dispose さ れてからは以降のイベントは購読できなくなる

? .subscribeして.disposedする以外のパターン

せーたろせーたろ

IBOutlet から Observable の作成

ユーザ入力をイベントのストリームとして ViewModel へ伝えるため、IBOutlet な UI コンポーネ ントから Observable を作成する
usernameOutlet: UITextField!に対して、rx.text.orEmpty.asObservale() として メソッドを呼び出していき Observable<String>を取得

せーたろせーたろ

ViewModel の出力を View にバインド

ViewModel で処理したプレゼンテーションロジックは、出力のストリームとして View にバインディングしないといけない

viewModel.signupEnabled
        .subscribe(onNext: { [weak self] valid in
               self?.signupOutlet.isEnabled = valid
               self?.signupOutlet.alpha = valid ? 1.0 : 0.5 
        })
        .disposed(by: disposeBag)

subscribe メソッドの onNext クロージャでsignupEnabled ストリームの変化を Bool として取得するsignupOutlet: UIButton!の isEnabled および alpha プロパティにバインディングして変化させている

せーたろせーたろ

まとめ

  • Observable を共有せず購読した場合にその数だけ Observable のイベントが実行される
  • 共有していない Observable は Cold Observable と呼ばれる
  • Observable を共有することで実行の無駄を避けることが出来る
  • 共有することによって Hot Observable と呼ばれる