The SwiftUI tutorial uses the @State
keyword to indicate mutable UI state:
@State var showFavoritesOnly = false
It offers this summary:
State is a value, or a set of values, that can change over time, and that affects a view’s behavior, content, or layout. You use a property with the @State attribute to add state to a view.
- What does the keyword mean, exactly?
- How does mutating a
@State
variable cause the view to be recomputed? - How are other variables immutable within the
body
getter?
The @State
keyword is a @propertyWrapper
, a feature just recently introduced in Swift 5.1. As explained in the corresponding proposal, it's sort of a value wrapper avoiding boilerplate code.
Sidenote: @propertyWrapper
has previously been called @propertyDelegate
, but that has changed since. See this post for more information.
The official @State documentation has the following to say:
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 mutating the value. To access a state’s underlying value, use its value property.
So when you initialize a property that's marked @State
, you're not actually creating your own variable, but rather prompting SwiftUI
to create "something" in the background that stores what you set and monitors it from now on! Your @State var
just acts as a delegate to access this wrapper.
Every time your @State
variable is written, SwiftUI
will know as it is monitoring it. It will also know whether the @State
variable was read from the View
's body
. Using this information, it will be able to recompute any View
having referenced a @State
variable in its body
after a change to this variable.
Its explained nicely with an example in the WWDC video - Session 204 (starts at 16:00, quotation starts at 20:15)
One of the special properties of
@State
variables is that SwiftUI can observe when they're read and written. Because SwiftUI knows thatzoomed
was read inbody
, it knows that the view's rendering depends on it. Which means - when a variable changes the framework is going to ask forbody
again using the new@State
value.
The @State
as a Property Wrapper is also elaborated and justified in Data Flow Through Swift UI (5:38) WWDC vid as well. It's shown how it solves the problem when we need a mutable value in an immutable (struct
) View
.
Let me add something else if you know React Native.
The @State
property is very like the this.state
object in React Native.
For example:
struct Foobar: some View {
@State var username = ""
}
class Foobar extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
};
}
}
When you modify the username variable, they will have the same effect, that re-render the current page.
If you click into @State
you can see that it has several getters. One with Value
another with Binding<Value>
.
SwiftUI seems to rely heavily on reactive programming (and their new Combine
framework, and since we cannot see the full implementation of these wrappers, I would expect that the values that are stored through @State
property wrappers are being managed by a CurrentValueSubject
from Combine
. Like the name implies, this essentially stores the current value, which can then be used as a bindable property by using the $
syntax.
If you know about C# and windows development. @State
is similar if not the same as x:Bind
or Binding
.. On a collection it is similar if not the same as ObservableCollection
.
As fredpi said, SwiftUI is listing for updates on vars with the @State
property delegate.
来源:https://stackoverflow.com/questions/56438730/what-does-the-swiftui-state-keyword-do