導入
画面が育つと、View の中に計算や通信まで詰め込んでゴチャゴチャに。そこで、画面(View)と、その裏方のデータ・ロジック(ViewModel)を分ける設計が MVVM です。
説明
MVVMは3つの役割に分けます。
graph LR M["Model<br/>データの型(struct)"] --> VM["ViewModel<br/>状態とロジック<br/>(ObservableObject)"] VM --> V["View<br/>見た目(SwiftUI)"] V -->|操作| VM
- Model … データのかたち(第4章の struct)。
- ViewModel … 画面が使う状態と、それを変えるロジック。
ObservableObjectにする。 - View … 見た目。ViewModelを
@StateObjectで持ち、状態を映すだけにする。
ViewModelは class で作り、ObservableObject に準拠、変化を画面に伝えたいプロパティに @Published を付けます。
import SwiftUI
class CounterViewModel: ObservableObject {
@Published var count = 0
func increment() {
count += 1
}
}
struct ContentView: View {
@StateObject private var vm = CounterViewModel()
var body: some View {
VStack {
Text("カウント: \(vm.count)")
Button("+1") { vm.increment() }
}
}
}
@Published var count が変わると、@StateObject で持っている画面が自動で更新されます。第6章の @State はViewの中の小さな状態、@StateObject+ObservableObject は 画面をまたいで共有する大きな状態やロジック 向け、と使い分けます。
まとめ
- View(見た目)/ViewModel(ロジック)/Model(データ) に分けると保守しやすい。
- ViewModelは
class + ObservableObject + @Published。 - Viewは
@StateObjectでViewModelを持ち、状態を映すことに専念する。