ざっくり
- ViewModelのような、Viewに1対1で対応したObservableObjectは不要なのではないか
- ViewModelの利用を削除し、以下のような変更を加えたら良いのではないか
- View側は
- StoreをenvironmentObjectとして監視
- ※画面に縛られずにDomainに関する状態を保持するオブジェクト=Store
- ViewModel内部に並んでいた変数ごとに、@Stateとして保持する
- ViewModel内部に記載していたロジックは、View側に寄せる
- StoreをenvironmentObjectとして監視
- View側は
メリット
- Combineのことを忘れられる
- ViewModelを用いた書き方だと、SwiftUIのViewのinitializer内部でCombine風の記載が生まれる

- ViewModelを用いた書き方だと、SwiftUIのViewのinitializer内部でCombine風の記載が生まれる
- ViewModelを用いた書き方だと、SwiftUIのViewのイニシャライザに渡す値(あるいは、そのイニシャライザ内部で生成されているViewModelに渡す値)をEnvironmentObjectから取得したいケースがあるが、イニシャライザ内部でアクセスできない点で不便であった

- なぜ今までViewModelが求められていたのか
- UIKitとの共存問題
その他考慮する点
- テストできる?
- environmentに突っ込むオブジェクトに関しては差し替え可能だが、Viewのメソッドのテストはできない
- 返却値が some Viewになってしまう

- その他、以下のような意見
- そもそもPreviewで静的な表示の確認はできる
- ロジックだけ別のModelに切り出してModelをテストすればよくない
- それでも担保できないならUITestでよくないか
- environmentに突っ込むオブジェクトに関しては差し替え可能だが、Viewのメソッドのテストはできない
- ViewのコードがFatにならないか?
- extensionでロジックとレイアウトを分けるだけでも見通しの良さを保ちつつ開発速度を上げることができそう
- ロジックを適切にモデルに切り出して抑えることもできる
- 結局ViewModel的なのになってしまう可能性はある
- ObservationFrameworkを使えるなら、そもそも以下の問題は発生しない?
- そもそもViewModelがObservableObjectであり、かつ、ObservableObjectを子に持つ場合に、「繋ぎこみ」処理を書く必要がある
- 繋ぎこみとは、ViewModelのイニシャライザ内部でCombineを用いた更新の伝播に関わる記述のこと
- この問題は、ObservableObjectがネストされている場合、ComputedPropertyによる演算では、子の変更が親に伝わらない仕組みであるため起こる
- → ObservationFrameworkでは上記問題が解消される
- そもそもViewModelがObservableObjectであり、かつ、ObservableObjectを子に持つ場合に、「繋ぎこみ」処理を書く必要がある
備忘録
- StoreのイニシャライザでRepositoryをany HogeProtocol型を指定してインジェクトする
- ジェネリクスを用いるコトもできなくはないが、型パラメーターのバケツリレーをせずにEnvironment経由で取得したいので
- 2023のiOSDC SVVSアーキテクチャ
- Store-View-ViewStateの略
- MVStateパターンも似た課題感
- SwiftUIで設計のシンプルさを重視してアプリ作るなら、ViewModel的なのをやめたほうが良いという趣旨は同じ
技術メモ
