Search code examples
iosswiftiphoneswiftuiuikit

Why doesn't custom SwiftUI view react to state changes


I've had this issue with many different custom views in SwiftUI, so why does code such as

struct HeaderText: View {
    @State var text: String
    @State var color: Color
    
    var body: some View {
        Text(text)
            .font(.custom("Gilroy-SemiBold", size: 20))
            .foregroundColor(color)
    }
}

not update automatically when text or color changes. For instance, if I had a view such as

struct ContentView: View {
    @State var text = "Hello"

    var body: some View {
        VStack {
            HeaderText(text: self.text, color: .black)
            Button("Change Text") {
                self.text = "Goodbye"
            }
        }
    }
}

I would have expected for the view to update with the new text, but it doesn't. I know you can accomplish this with @Binding, but I'm looking for a more elegant solution, similar to how Text works. I'm just using these views and structs as an example, so I'm aware these may not be best practices in general.

Thank you for the help!


Solution

  • SwiftUI is a functional programming thing. Structs are value type( not reference type). Structs are normally immutable.

    You can simply have lets in your sub view struct.

    Why - SwiftUI re-create your views when @State changes instead of modifying it. This is done by calling the body again.

        struct HeaderText: View {
            let  text: String //<= here
            let  color: Color //<- here
            
            var body: some View {
                Text(text)
                    .font(.custom("Gilroy-SemiBold", size: 20))
                    .foregroundColor(color)
            }
        }
    
    

    Why does not the code which is in the question work ,

    It is because those state variables initialise with the given value (inside parent view ) as well as non of changes done to @state which is inside child view (HeaderText) Because @State can be change inside within the view itself.