Understanding State in SwiftUI
Building pretty looking views is super easy with SwiftUI, but apps need to be more than just something nice to look at. Apps need to do things, then give the user feedback by updating the UI accordingly. With SwiftUI in order to update a View you need to change its state.
What is @State?
@State
is what is called a property wrapper. When you add the @State
property wrapper to a property on your View you are telling SwiftUI to move the data to shared storage that is managed by SwiftUI. Since SwiftUI creates and destroys structs all the time as it updates views, this allows the state of a view to stick around instead of being tossed away. In a sense State properties are the source of truth for what data should be displayed to the user.
Using @State to Update a Label
Let’s look at an example using a property marked as @State:
struct ContentView: View {
@State private var numberOfButtonPushes = 0 // 1
var body: some View {
VStack(spacing: 50) {
if numberOfButtonPushes == 0 { // 2
Text("Push the button")
} else {
Text("\(numberOfButtonPushes)") // 3
}
CircleButton(action: {
self.numberOfButtonPushes += 1 // 4
})
}
}
}
This code places a button (in this case a custom circle button) on the view with a label above it. The label starts out saying “Push the button”, then changes to display the count for the number of times you have pushed the button.
Breaking down the code:
The property
numberOfButtonPushes
is our state variable. This is used later on to keep track of the number of button pushes and update our view.If the user hasn’t pushed the button yet then
numberOfButtonPushes
will still be 0, so the text is set to “Push the button”Once the user presses the button the text will update to display the count.
Increment
numberOfButtonPushes
by 1 every time the user pushes the button
Pretty straightforward, right?
One interesting thing to note is without having the numberOfButtonPushes
property marked as @State
incrementing it by 1 here wouldn’t be possible. The reason for that is in SwiftUI Views are structs, which are value types and inherently immutable. That means updating the value of a property is out of the question. Adding the @State
property wrapper not only moves it to SwiftUI’s managed storage, it also makes the property mutable so you can update it. Then the rest of your SwiftUI code just responds to the state of each of your properties and updates the View to match.