SwiftUI @State の基本と値型の管理

SwiftUI のビューは構造体であり、通常はプロパティを直接変更できない。しかし UI では、ボタンのタップやテキスト入力に応じて画面を更新する必要がある。この問題を解決するのが @State プロパティラッパーだ。

@State の役割

@State を付けたプロパティは、SwiftUI のフレームワークが管理する専用のストレージに値を保持する。ビューの構造体自体が再生成されても、@State の値は維持され、値が変わるとビューが自動的に再描画される仕組みになっている。

struct CounterView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("カウント: \(count)")
            Button("増やす") {
                count += 1
            }
        }
    }
}

このコードでは count@State を付けることで、ボタンをタップするたびに値が更新され、Text の表示も連動して変わる。@State がなければ、構造体のプロパティは不変(immutable)のためコンパイルエラーとなる。

値型専用という特性

@StateStringIntBoolArray などの値型(Value Type)を管理するために設計されている。クラスのような参照型には @StateObject@Observable を使うのが適切であり、@State に参照型を渡しても期待通りに再描画されないケースが生じる。

値型(@State 向き)

Int、String、Bool、Array、独自の構造体など。コピーセマンティクスを持ち、変更を検知しやすい。

参照型(@State 向きでない)

クラスのインスタンス。参照が同じまま中身だけ変わると、SwiftUI が変更を検知できない場合がある。

private を付ける理由

Apple の公式ドキュメントでは、@State プロパティには private を付けることが推奨されている。状態はそのビュー自身が所有・管理するものであり、外部から直接アクセスさせる設計にすると、データフローが複雑になりバグの温床となりやすい。子ビューに値を渡したい場合は @Binding を使うのが正しいパターンだ。

// 推奨
@State private var isOn = false

// 非推奨(外部からアクセスできてしまう)
@State var isOn = false

複数の @State を使う

1 つのビューに複数の @State プロパティを持たせることも一般的だ。たとえばフォーム画面では、名前・メールアドレス・同意チェックなど、それぞれ独立した状態を管理する場面が多い。

struct ProfileFormView: View {
    @State private var name = ""
    @State private var email = ""
    @State private var agreedToTerms = false

    var body: some View {
        Form {
            TextField("名前", text: $name)
            TextField("メール", text: $email)
            Toggle("利用規約に同意", isOn: $agreedToTerms)

            Button("送信") {
                print("\(name), \(email), \(agreedToTerms)")
            }
            .disabled(!agreedToTerms)
        }
    }
}

$name のようにドル記号を付けると Binding<String> が得られ、TextField が直接値を読み書きできるようになる。この「プロジェクテッドバリュー」の仕組みは @Binding の記事で詳しく扱う。

@State と再描画の範囲

@State の値が変更されると、そのプロパティを参照しているビュー階層だけが再描画される。SwiftUI は差分検出を行い、変更が影響しない部分はスキップするため、パフォーマンスへの影響は最小限に抑えられる。

ただし、巨大な配列を @State で保持して頻繁に更新するようなケースでは、再描画コストが問題になることもある。そうした場面ではモデル層に処理を分離し、@StateObject@Observable と組み合わせる設計が望ましい。

@State を使うべき場面

トグルの ON/OFF、テキスト入力の一時保持、アラート表示フラグなど、そのビューだけで完結するシンプルな状態。

別の仕組みを検討すべき場面

複数のビューで共有する状態、ネットワークから取得したデータ、アプリ全体の設定など、ビューの外部に責任を持たせるべき状態。

@State は SwiftUI の状態管理における最も基本的なツールであり、すべてのプロパティラッパーの出発点となる。まずは @State でシンプルな値を管理することに慣れ、そこからより高度な仕組みへと段階的に進むのがよいだろう。