5

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)  
  }  
}  

2 Answers 2

8
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.

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

This is the only explanation that actually make sense. Thank you.
1

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)
  }
}

5 Comments

By doing that im getting the error: Argument labels '(wrappedValue:)' do not match any available overloads
@xyyx, updated with usage... it would be very helpful to start from developer.apple.com/tutorials/swiftui/tutorials
When i try to apply a value to the Binding variable, i get this error: Cannot convert value of type 'String' to expected argument type 'Binding<String>'. How do i convert a String value into a Binding<String> value?
@xyyx Asperis Example works if you just copy it...what is the problem?
Asperi, what is the reason to bind msg in ChildView? There is no reason for that, if you don't like to change the value in "parents" state variable. It is only confusing for understanding, how State / Binding works and for what it is designed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.