なんとく「対」で使う雰囲気だけで使っていた @State と @Binding。
そうでもないらしい。
🔄 @Binding はいらない
親のカウンターの値を子に渡す。
struct Parent: View {
// Left side of mutating operator isn't mutable: 'self' is immutable
// private var count = 0
@State private var count = 0
var body: some View {
VStack {
Button("\(count)") {
count += 1
}
Child(count: count)
}
.padding()
.background(.yellow)
}
}
struct Child: View {
let count: Int
var body: some View {
Text("\(count)")
.padding()
.background(.white)
}
}
どうやら、子で @Binding を付けずに受け取っても再描画される。
@State がなくても伝わる? と思ったが不可。
struct 内のプロパティは var でも immutable
らしい。
🔄 @Binding を付ける
親に「$」、子に「@Binding」を付けて渡す。
struct Parent: View {
@State private var count = 0
var body: some View {
VStack {
Button("\(count)") {
count += 1
}
Child(count: $count) // *
}
.padding()
.background(.yellow)
}
}
struct Child: View {
@Binding var count: Int // *
var body: some View {
Text("\(count)")
.padding()
.background(.white)
}
}
挙動は、最初と同じ。
あれ、@Binding って何だったの?
🔄 子で値を更新する
今度は、子でも受け取った値を更新してみます。
struct Parent: View {
@State private var count = 0
var body: some View {
VStack {
Button("\(count)") {
count += 1
}
Child(count: $count)
}
.padding()
.background(.yellow)
}
}
struct Child: View {
@Binding var count: Int
var body: some View {
Button("\(count)") {
count -= 1 // *
}
.padding()
.background(.white)
}
}
親も更新されます。
双方向に再描画できるようです。
Jetpack Compose では「単方向」のみですが、その前の Android View でいうところの「View Binding」に似ています。
🔄 まとめ
- struct 内のプロパティは var でも変更できないので @State を付ける。
- その値の変化は子に再描画を @Binding なしで伝播できる。
- 子で @Binding で受ければ、さらに親にも伝播できる。
参照してるイメージというべきか。