データフロー
SwiftUI の状態管理の全体像。
選択の指針#
| 状況 | 使うもの |
|---|---|
| この View だけが持つ値 | @State |
| 親の値を子が読み書きする | @Binding |
| 参照型のモデルを所有する | `State + @Observable |
| 親から渡された Observable | ただの let |
| 階層全体で共有する | @Environment |
| 永続化する | `AppStorage、SwiftData |
| 変わらない値 | let |
単一の情報源#
同じ情報を 2 か所に持たないこと。
swift
// 悪い例 — ずれる
var items: [Item]
var itemCount: Int
// 良い例 — 導出する
var items: [Item]
var itemCount: Int { items.count }導出できるものは状態にしない。 状態が増えるほど、整合を保つ責任が増える。
所有権は上に、Binding は下に#
[@State を持つ View] ← 所有者は 1 つ
↓ $value
[@Binding で受ける View]
↓ $value
[@Binding で受ける View]状態はそれを必要とする View すべての共通の祖先に置く。 高すぎると再描画の範囲が広がり、 低すぎると兄弟に共有できない。
再描画の範囲#
body が再評価される条件。
- `
Stateの値が変わった - 読んでいる `
Observableのプロパティが変わった - 親から渡された値(
Equatableで比較)が変わった
読んでいないプロパティは影響しない(`Observable の場合)。
性能問題が出たら、
状態を持つ部分を小さな View に切り出すのが第一手。
参考文献#
- Apple. Managing model data in your app. https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app
- Apple. Data Essentials in SwiftUI. WWDC 2020. https://developer.apple.com/videos/play/wwdc2020/10040/