Types in Swift fall into one or two categories (value types and reference types). Value types are where each instance keeps a unique copy of its data, usually defined as a struct, enum or tuple.
In SwiftUI we use structs for our views and since structs are value types we cannot modify the values inside the struct directly.
To be able to modify the values in a struct we can use the @State property wrapper.
We declare a property with a @State attribute and provide an initial value, this moves the property storage out from the struct into a managed storage in SwiftUI. When the value changes, SwiftUI will recreate the struct and maintain the value of the property.
From the Official Quick Help:
SwiftUI manages the storage of any property you declare as a state. When the state value changes, the view invalidates its appearance and recomputes the body. Use the state as the single source of truth for a given view.
A State instance isn’t the value itself; it’s a means of reading and writing the value. To access a state’s underlying value, use its variable name, which returns the wrappedValue property value.
You should only access a state property from inside the view’s body, or from methods called by it. For this reason, declare your state properties as private, to prevent clients of your view from accessing them. It is safe to mutate state properties from any thread.
To pass a state property to another view in the view hierarchy, use the variable name with the
$
prefix operator. This retrieves a binding of the state property from its projectedValue property. For example, in the following code examplePlayerView
passes its state propertyisPlaying
toPlayButton
using$isPlaying
:
Additional tips:
- Generally use @State in the same View
- If you want pass the @State to other views, it is probably best to use other mechanisms such @ObservedObject, @StateObject and @EnvironmentObject (all views refresh when the value changes)- I’ll cover these in separate posts.