Reputation: 153
I have a Swift ui view with a child witch gets values from a @State variable. When i update my @State variable the view rebuilds but the child stays the same.
struct ContentView: View {
@State var msg: String = ""
var body: some View {
VStack {
Button(action: {
self.msg = "Hallo World"
}, label: { Text("Say Hallo")})
ChildView(msg: msg).padding().background(Color.orange)
Text(msg).padding().background(Color.green)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct ChildView: View {
@State var msg: String
var body: some View {
Text(msg)
}
}
Upvotes: 5
Views: 3007
Reputation: 17534
import SwiftUI
struct ContentView: View {
@State var msg: String = ""
var body: some View {
VStack {
Button(action: {
self.msg += "Hallo World "
}, label: { Text("Say Hallo")})
ChildView(msg: msg).padding().background(Color.orange)
Text(msg).padding().background(Color.green)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct ChildView: View {
var msg: String
var body: some View {
Text(msg)
}
}
You don't need any state property wrapper in your ChildView. Once msg changed, SwiftUI know, that every View depending on its value should be "reloaded".
In your example, you "fixed" it by wrapping initial value to its state property wrapper. SwiftUI will not reload it, because @State property wrapper means, the value is stored outside of the ChildView. @State property wrapper in not part of View state. It is the opposite, once the @State wrapped property change, SwiftUI will reevaluate View's body computed property. To "reset" @State property wrapped value, you need "recreate" it, which means the state property will be reset to its initial value too.
Upvotes: 7
Reputation: 257493
Use in it @Binding instead of @State. Modified complete snapshot provided below. Tested as-is & works with Xcode 11.2 / iOS 13.2.
struct ContentView: View {
@State var msg: String = ""
var body: some View {
VStack {
Button(action: {
self.msg = "Hallo World"
}, label: { Text("Say Hallo")})
ChildView(msg: $msg).padding().background(Color.orange)
Text(msg).padding().background(Color.green)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct ChildView: View {
@Binding var msg: String
var body: some View {
Text(msg)
}
}
Upvotes: 1