はじめに
iOSでMVVMアーキテクチャを採用した開発に取り組んでいます。 MVVMと言っても、RxSwiftやReactiveKitのようにReactive Programmingを実現するためのフレームワークは用いずに、単純な形にすることを目標に考えた方法について記載します。
こちらの記事 [MVVM: A non-reactive introduction] (https://medium.com/@IanKeen/mvvm-a-non-reactive-introduction-5a1f33402a32#.kok2bhglh)の内容を参考にさせていただいております。
iOSはMVC
iOSのアプリケーションアーキテクチャには、MVCが採用されています。
Model-View-Controller - Apple Developer
そのため、特殊なことをしなければ、それぞれのクラスはModel, View, Controller層に分かれアプリケーションが構成されます。
しかし、MVCでアプリを開発していると、次第にViewControllerが肥大化していくという問題は、誰もが通る道かと思います。 その問題を解決すべく、様々なアーキテクチャが提案されています。
まだMVC,MVP,MVVMで消耗してるの? iOS Clean Architectureについて
MVVM
MVVMについての説明は省略しますが、もともとはWPFやSilverlight, Windows Store AppなどMicrosoft系の開発において採用されているアーキテクチャです。
MVVM (Model-View-ViewModel) - Wikipedia
MVVMで重要になるのが、データバインディングですが、XAMLによってデータバインディングがプラットフォームレベルで可能になっているため、Microsoft系の開発ではMVVMを採用しやすくなっています。
iOSにMVVMを導入すると、ViewControllerの肥大化を防げたり、Viewの操作とビジネスロジック部分をわけやすくなるため、全体の構成がわかりやすくなります。 しかし、最初に述べたように、iOSはそもそもMVCアーキテクチャなので、単純にはMVVMアーキテクチャにできません。
フレームワーク?
iOSでMVVMを実現するには、先に述べたRxSwiftやReactiveKitなどのフレームワークを導入したり、バインディング機構を自作するという方法があります。
個人的には、独特な記述が要求される、このようなフレームワークの導入にはあまり気がのりません。 独特な記述によって余計に複雑になったり、ロックインされてしまってもしもの時に移行しにくいというリクスもあると思うからです。
Cocoaだと、Cocoa-Bindingがサポートされていますが、残念ながらiOSにはCocoa-Bindingがサポートされていません。
バインディングを捨てる、単純にViewModel層を導入する
MVVMは、データバインディングによってデータとビューを宣言的に結び付けられるところが良いところの一つですが、バインディングしなくともViewModelは導入できます。
値の更新は、自分で記述する必要がありますが、ViewControllerの肥大化を防げたり、Viewの操作とビジネスロジック部分をわけやすくなるなどのメリットは十分にあります。また今から述べる方法だとアプリケーション全体をMVVMにする必要はなく、一部の分離したいところを分離するといったこともやりやすいと考えています。
全体像
View, ViewModel, ViewModelStateを使います。ViewControllerは、Viewに含みます。
ViewModelState
ViewModelが取り得る状態を表します。
ViewModel
stateDidUpdate
というプロパティを持ち、ViewModelStateを渡して、Viewに更新を通知します。
ViewModelというプロトコルを作り、各種ViewModelクラスを定義します。
View
ViewModelを持っていて、viewDidLoad
でviewModel
のstateDidUpdate
を設定し、viewModel
の更新を受け取ります。
サンプル
サンプルプロジェクトをGitHubに作成しています。 NoBindingMVVMSample 一度見てみてください。
エンジニアリング iOS Swift MVVM Apple
関連記事
-
2024/3/24
try! Swift Tokyo 2024
try! Swift Tokyo 2024の参加メモ
Swift
-
2023/1/31
SwiftUIでTabBarを非表示にする
SwiftUI TabBar
-
2023/1/14
Bootstrap5.3で追加されたダークモードに対応してみました
Bootstrap DarkMode
-
2021/2/17
brew upgradeで Your CLT does not support macOS 11というエラーがでた
homebrew macOS Big Sur
-
2020/12/1
Apple Silicon搭載 MacBook Pro M1で Homebrewとrbenvをインストールする
先日購入したApple Silicon搭載 MacBook Pro M1にこのブログをビルドするためにHomebrewとrbenvをインストールしたのでメモ。
Apple Silicon Homebrew rbenv
-
2020/11/27
Apple Silicon搭載のMacBook Pro M1が危うく文鎮化するところだったので記録
Apple Silicon搭載のMacBook Pro 13インチを仕事用に購入したのですが、クリーンインストールしたところ文鎮化しかけたので記録しておきます。
MacBook Pro Apple Apple Silicon M1
-
2020/6/23
Platform State of the Unionまとめ
Platform State of the Unioまとめ
WWDC2020 Apple アップル iOS macOS watchOS tvOS
-
2020/6/23
WWDC2020キーノートまとめ
WWDC2020 キーノートまとめ
WWDC2020 Apple アップル iOS macOS watchOS tvOS
-
2020/5/31
GitHub Pagesで無料ブログを作成する - Part4 自分のオリジナルのテーマを作る
Jekyllでは既存のテーマを使うこともできるのですが、さらに一歩踏み込んで、自分で既存のテーマをカスタマイズしたり、テーマを作ることもできます。
GitHub Pages ブログ
-
2020/5/28
GitHub Pagesで無料ブログを作成する - Part3 Jekyllの設定をカスタマイズする
前回の記事では、Jekyllのテーマを利用する方法と記事を追加する方法を紹介しました。今回はさらにJekyllをカスタマイズしていきますが、確認を簡単にするためにまずJekyllをローカル環境で実行する方法を紹介します。
GitHub Pages ブログ