What does the SwiftUI `@State` keyword do?

烈酒焚心 提交于 2019-11-28 21:17:39

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 that zoomed was read in body, it knows that the view's rendering depends on it. Which means - when a variable changes the framework is going to ask for body 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!