简体   繁体   中英

Changing @State variable does not update the View in SwiftUI

I have a following View (took out irrelevant parts):

struct Chart : View {
    var xValues: [String]
    var yValues: [Double]
    @State private var showXValues: Bool = false

    var body = some View {
        ...
        if showXValues {
            ...
        } else {
            ...
        }
        ...
    }
}

then I wanted to add a way to modify this value from outside, so I added a function:

func showXValues(show: Bool) -> Chart {
    self.showXValues = show
    return self
}

so I build the Chart view from the outside like this:

Chart(xValues: ["a", "b", "c"], yValues: [1, 2, 3])
    .showXValues(true)

but it works as if the value was still false. What am I doing wrong? I thought updating an @State variable should update the view. I am pretty new to Swift in general, more so to SwiftUI, am I missing some kind of special technique that should be used here?

As in the comments mentioned, @Binding is the way to go.

Here is a minimal example that shows the concept with your code:

struct Chart : View {
    var xValues: [String]
    var yValues: [Double]
    @Binding var showXValues: Bool

    var body: some View {
        if self.showXValues {
            return Text("Showing X Values")
        } else {
            return Text("Hiding X Values")
        }
    }
}

struct ContentView: View {
    @State var showXValues: Bool = false

    var body: some View {
        VStack {
            Chart(xValues: ["a", "b", "c"], yValues: [1, 2, 3], showXValues: self.$showXValues)
            Button(action: {
                self.showXValues.toggle()
            }, label: {
                if self.showXValues {
                    Text("Hide X Values")
                }else {
                    Text("Show X Values")
                }
            })
        }
    }
}

Okay, answer is pretty dumb.

There is no need to create func -s. All I have to do is not mark the properties as private but give them an initial value, so they're gonna become optional in the constructor. So user can either specify them, or not care. Like this:

var showXLabels: Bool = false

This way the constructor is either Chart(xLabels:yLabels) or Chart(xLabels:yLabels:showXLabels) .

Question had nothing to do with @State.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM