joels
joels

Reputation: 7711

Why doesn't the Text update when using @Binding?

The Working works as expected.

But using the @Binding in the NotWorking example, doesn't seem to update the Text control. Why doesn't the @Binding version work, what am I missing here?

Initial Launch: Initial Launch

After Typing: After typing

struct Working: View {
    //Binding from @State updates both controls
    @State private var text = "working"
    
    var body: some View {
        VStack {
            TextField("syncs to label...", text: $text)
            Text($text.wrappedValue)
        }
    }
}
struct NotWorking: View {
    //Using the @Binding only updates the TextField
    @Binding var text: String
    
    var body: some View {
        //This does not works
        VStack {
            TextField("won't sync to label...", text: $text)
            Text($text.wrappedValue)
        }
    }
}

struct Working_Previews: PreviewProvider {
    @State static var text = "not working"
    static var previews: some View {
        VStack {
            Working()
            NotWorking(text: $text)
        }
    }
}

Upvotes: 1

Views: 435

Answers (2)

joels
joels

Reputation: 7711

Thanks to @George_E. I define @State in a wrapper view and display that for the preview. The WrapperView simply displays the control that I want to preview but it contains the State.

Working

struct Working_Previews: PreviewProvider {
    //Define the State in a wrapper view
    struct WrapperView: View {
        @State var text = "Preview is now working!!!"
        var body: some View {
            NotWorking(text: $text)
        }
    }

    static var previews: some View {
        VStack {
            Working()
            //Don't display the view that needs the @Binding
            //NotWorking(text: $text)
            //Use the WrapperView that has @State and displays the view I want to preview.
            WrapperView()
        }
    }
}

Upvotes: 0

George
George

Reputation: 30341

Static @States don't work. It's the fact that it being static means that the struct Working_Previews isn't mutated when text is changed, so it won't refresh.

We can test this by changing from a PreviewProvider to an actual View:

struct ContentView: View {
    
    @State static var text = "not working"
    
    var body: some View {
        VStack {
            Working()
            NotWorking(text: ContentView.$text)
        }
    }
}

This code gives the following runtime message:

Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update.

Upvotes: 2

Related Questions