見出し画像

[SwiftUI]SwiftUIでの状態変化@State

1. @Stateとは?

構造体のプロパティに対して@State属性を付与することで、以下の2つのことができるようになる。

・構造体の中でプロパティの値を更新すること
・値が更新されたら関連するViewを再描画させること

2. 構造体の中のプロパティの値を更新

構造体は、基本的にプロパティの値を変更することはできないが、@State属性を付与することで、プロパティの値を変更することが可能になる。
「mutating」を構造体の関数に指定すれば変更可能であるがそれと同じようなイメージ。
まずはmutatingを使用して構造体のプロパティを変更するパターン。

struct Profile {
    let name: String
    var hobbies: [String]

    init(name: String, hobbies:[String]) {
        self.name = name
        self.hobbies = hobbies
    }

    mutating func addHobby(hobby: String) {
        hobbies.append(hobby)
    }
}

var profile = Profile(name: "Tom", hobbies: ["soccer"])
print(profile.hobbies) // ["soccer"]
profile.addHobby(hobby: "baseball")
print(profile.hobbies) // ["soccer", "baseball"]

次に以下はSwiftUIの@Stateを使用してプロパティを変更するパターン。

struct ContentView {
    @State var number = 1

    var body: some View {
        VStack {
            Text("\(number)")
            Spacer()
            Button("Add Number") {
                number += 1
            }
        }
    }
}

3. 値が更新できないパターン

以下のようにプロパティに@Stateをつけても、関数内での値変更が行われない場合もある模様。単なる構造体だから?

struct MyProfile {
    let name: String
    @State var hobbies: [String]

    init(name: String, hobbies:[String]) {
        self.name = name
        self.hobbies = hobbies
    }

    func addHobby(hobby: String) {
        hobbies.append(hobby)
    }
}

var profile = Profile(name: "Tom", hobbies: ["soccer"])
print(profile.hobbies) // ["soccer"]
profile.addHobby(hobby: "baseball")
print(profile.hobbies) // ["soccer"] ← baseballがない

4. 関連するViewの再描画

まずはサンプルコード。
「Add Number」がタップされるとContentViewのプロパティ「number」が+1され、「number」の値が画面に表示されるというもの。

struct ContentView {
    @State var number = 1

    var body: some View {
        VStack {
            Text("\(number)")
            Spacer()
            Button("Add Number") {
                number += 1
            }
        }
    }
}

numberが+1されたタイミングで、numberを参照している「Text」が再描画される。

5. 終わりに

構造体のプロパティの値が更新できないパターンもあるようで、注意する必要がある。


この記事が気に入ったらサポートをしてみませんか?