ReSwiftをためした所感

現在仕事で開発中のiOSアプリにReSwiftを導入できないか検討した。

結論としては今回は導入を見送ったが、良いと感じた部分が沢山あったので雑な作業メモを転記する。

ReSwift とは

Redux は複雑な状態を管理するために生まれたJS発祥の技術

そのRedux をSwiftに移植したものがReSwift

ReSwift/ReSwift: Unidirectional Data Flow in Swift - Inspired by Redux

こちらに大変わかりやすくまとまっている

ReSwiftでアプリの状態管理 / Reactive Swift Meetup // Speaker Deck

モチベーション

  • アプリ全体で共有する状態の管理をうまくしたい
  • グローバルなスコープのシングルトンにアプリの様々な箇所からアクセスするのは不健全な気がした

インストールから簡単に使うところまでの作業メモ

まずは以下のリポジトリをそのままアプリに移植し、それを拡張していった

ReSwift/CounterExample: Demo Application of Unidirectional Data Flow in Swift, Built with ReSwift

ReSwift を Cartfile に追加

$ carthage update --platform iOS --no-use-binaries

ReSwift の設定をプロジェクトに反映

AppState を作成

  • アプリ全体の状態を持つ
  • Action からしか変更できない

CounterReducer を作成した

  • counterの状態を変更する Reducer
  • AppState を返す状態を持たない関数

Actions を作成した

  • Action protocol を実装した struct として定義する

  • subscribe すると、最初に newState が呼ばれて現在の state が降ってくる

  • 最初の state は 特に action をdispatchしていないので、ReSwiftinit 型になっている
  • action を dispatch すると、その結果また newState が呼ばれて状態の更新が通知される
  • subscribe しないで dispatch することもできる

    • 状態は変更できるが、newStateに通知されない
  • ネットワークエラーでアラートを出したいときはどうする?

    • ErrorActionを発行して、subscribeしているViewControllerで新しいstateに応じてエラーを表示する

アプリアーキテクチャに関する考察

  • MVP(Clean Architecture) に適用する場合

    • ビジネスロジックをUseCaseの代わりにActionに書いて、それをPresenterから呼ぶ
    • StateはPresenterでsubscribeする
    • ビジネスロジックは Action にとどめておいて、 Reducerは状態の管理に徹する
    • newState に降ってくるイベントは今まで通りViewControllerにdelegateする
  • Redux にすることで、今までdelegate とかクロージャでばらばらに受け取っていたコールバックを1つのメソッドで、1つの状態として扱えるようになる

引数とメソッド呼び出しについて

  • データを fetch するaction で引数にデータを渡さなくても、クロージャのstate を通じて、欲しい状態を取れるようになる
  • ようするにグローバル変数と変わらないのだが、状態の変更 をAction, Reducer を用いるよう制限することで、データの流れを把握しやすくする

Promise を使った非同期処理の連結

Reducer の分割について

How could i use multiple reducer in Reswift 4.0.0 · Issue #241 · ReSwift/ReSwift いいかんじ

ユニットテスト

まだ書いたことはないが、Action は基本的に状態を持たないのでテストは書きやすそう

デバッグのしやすさ

  • クラッシュした時のStateをキャプチャできるので、再現してデバッグするのが簡単になるのではないか
  • ReSwift Recorderという仕組みもある

やめた理由

  • 今後自分以外の人も保守することを考えると、ReSwiftにロックインされるのはあまり良くない
  • 今開発中のアプリは大量の状態を持っているわけではないので、現状の要件にはそこまでマッチしていない
  • newState の取り回しが若干面倒な気がしている
  • pros が cons を上回るなら導入も吝かではない
    • もう少し練度が上がればスムーズに使っていけるのかもしれない