MVVMパターン
View、ViewModel、Modelの役割を分離します。
「MVVMパターン」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
MVVMとは
MVVM は Model-View-ViewModel の略です。アプリを3つの層に分け、それぞれに明確な責務を1つずつ持たせるアーキテクチャパターンです。
- Model — データとビジネスルール
- View — ユーザーに表示するもの
- ViewModel — ModelのデータをView向けに整える橋渡し役
目的は関心の分離です。それぞれの層が、他の層とは独立して、それぞれ固有の理由で変更できるようにします。
Model層
Model は、元になるデータと、それを管理するルールを保持します。画面や表示方法については何も知りません。
Modelは通常、単純なstructやドメインオブジェクトとして表現します。UIへの依存がないため、簡単にテストできます。
struct User {
let id: UUID
let firstName: String
let lastName: String
let isPremium: Bool
}
struct Order {
let items: [String]
let total: Decimal
}View層
View は表示だけを担当します。SwiftUIでは View struct、UIKitでは UIViewController とそのサブビューが該当します。
よいViewにはビジネスロジックを含めません。状態を描画し、ユーザーの操作をViewModelへ伝えるだけです。
struct ProfileView: View {
@StateObject var viewModel: ProfileViewModel
var body: some View {
VStack {
Text(viewModel.displayName)
if viewModel.showBadge {
Text("Premium")
}
}
}
}ViewModel層
ViewModel はModelとViewの間に位置します。元のModelデータを受け取り、Viewがそのまま表示できる表示用の値に変換します。
また、ユーザーが操作したときにViewから呼び出す意図(メソッド)も公開します。
final class ProfileViewModel: ObservableObject {
@Published var displayName: String
@Published var showBadge: Bool
init(user: User) {
displayName = user.firstName + " " + user.lastName
showBadge = user.isPremium
}
}なぜ関心を分離するのか
フォーマット、ネットワーク処理、描画がすべてビューコントローラー内で絡み合うと、そのファイルは巨大でテストできない塊になってしまいます。
責務を分割すると、次のようになります。
- Modelを複数の画面で再利用できます
- ViewModelをUIなしで単体テストできます
- Viewを小さく宣言的に保てます
Modelに属するもの
Modelには次のものを置きます。
- ドメインエンティティ(
User、Product) - ビジネス上の検証ルール
- 永続化とネットワーク処理の抽象化(多くの場合、ViewModelが呼び出すサービスを通じて行います)
UI文字列、色、フォーマットをModelに置くことは絶対に避けてください。
ViewModelに属するもの
ViewModelはプレゼンテーションロジックを担当します。
- 日付、通貨、名前を表示用の文字列にフォーマットする
- 表示するUIの状態(読み込み中、エラー、空の状態)を決める
- サービスの呼び出しを調整し、結果を公開する
final class CartViewModel: ObservableObject {
@Published var totalText: String = ""
func update(with order: Order) {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
totalText = formatter.string(from: order.total as NSNumber) ?? "-"
}
}Viewに属するもの
Viewが行うべきことは次のものだけです。
- UI要素を配置して描画する
- ViewModelから公開された状態を読み取る
- ViewModelのメソッドを呼び出してタップやジェスチャーを伝える
View内にビジネスルールを決める if があるなら、そのロジックはおそらくViewModelに置くべきです。
MVVMにおけるデータフロー
データは一方向に流れ、アクションは逆方向に流れます。
- データは Model -> ViewModel -> View
- ユーザーの意図は View -> ViewModel
ViewがModelと直接やり取りすることはありません。これにより、依存関係がドメインに向かって内側を指す構造を保てます。
MVVMとMVCの比較
従来のMVCでは、フォーマット、ネットワーク処理、ビューの接続をすべてコントローラーが同時に担うため、コントローラーが巨大になりがちです。
MVVMでは、そのプレゼンテーションロジックをViewModelに切り出し、コントローラー(またはSwiftUIのView)を薄く保ちます。ViewModelはUIフレームワークに依存しないため、はるかに簡単にテストできます。
完全な一例
ここでは、各層を結び付けた小さいながらも完全なMVVMの一例を示します。
struct Account { let balance: Decimal }
final class AccountViewModel: ObservableObject {
@Published var balanceText: String
init(account: Account) {
balanceText = "$" + "\(account.balance)"
}
}
struct AccountView: View {
@StateObject var viewModel: AccountViewModel
var body: some View { Text(viewModel.balanceText) }
}クイックチェック
MVVMにおける責務の理解度を確認しましょう。
まとめ
MVVMの3つの層と、それぞれの境界を学びました。
- Model — UIを持たない、元のデータとビジネスルール
- ViewModel — プレゼンテーションロジックとユーザーの意図
- View — ViewModelの状態を純粋に描画する層
これらの関心を分離すると、コードがテストしやすく、再利用しやすく、理解しやすくなります。次は、バインディングを使ってViewModelとViewを接続します。
よくある質問
「MVVMパターン」レッスンは無料ですか?
はい。「MVVMパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「MVVMパターン」で何を学びますか?
View、ViewModel、Modelの役割を分離します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「MVVMパターン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。