SwiftUI `@State` 关键字有什么作用?

What does the SwiftUI `@State` keyword do?

SwiftUI tutorial使用@State关键字表示可变UI状态:

@State var showFavoritesOnly = false

它提供了这个摘要:

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.

@State 关键字是一个 @propertyWrapper,最近才在 Swift 5.1 中引入的一项功能。正如 corresponding proposal 中所解释的那样,它是一种避免样板代码的值包装器。


旁注:@propertyWrapper 以前被称为 @propertyDelegate,但此后发生了变化。有关详细信息,请参阅


official @State documentation 有以下说法:

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.

因此,当您初始化标记为 @State 的 属性 时,您实际上并不是在创建自己的变量,而是提示 SwiftUI 创建 "something"在后台存储您设置的内容并从现在开始监控!您的 @State var 只是作为一个 代表来访问这个包装器 .

每次 @State 变量被 写入 时,SwiftUI 都会知道它正在监视它。它还会知道 @State 变量是否从 Viewbody 读取 。使用此信息,它将能够 重新计算任何 View 在更改此变量后在其 body 中引用了 @State 变量。

如果您了解 C# 和 windows 开发。 @State 如果与 x:BindBinding 不同,则相似。在集合中,如果与 ObservableCollection 不同,则相似。

正如 fredpi 所说,SwiftUI 正在使用 @State 属性 委托列出 vars 的更新。

WWDC video - Session 204 中的示例很好地解释了它(从 16:00 开始,引用从 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.

作为 属性 包装器的 @StateData Flow Through Swift UI (5:38) WWDC vid 中也得到了详细说明和证明。它显示了当我们需要不可变 (struct) View.

中的可变值时如何解决问题

如果你了解 React Native,让我补充一些其他内容。

@State属性很像React Native中的this.state对象

例如:

struct Foobar: some View {
    @State var username = ""
}
class Foobar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      username: '',
    };
  }
}

当您修改用户名变量时,它们将具有相同的效果,re-render 当前页面。

如果你点击 @State 你可以看到它有几个 getter。一个 Value 另一个 Binding<Value>。 SwiftUI 似乎严重依赖反应式编程(及其新的 Combine 框架,并且由于我们看不到这些包装器的完整实现,我希望通过 @State 属性 包装器由来自 CombineCurrentValueSubject 管理。顾名思义,这实际上存储了当前值,然后可以通过使用 [=17] 将其用作可绑定的 属性 =]语法。

我喜欢斯坦福大学教授 Paul Hegarty 的解释。他说 @State 基本上将该变量转换为指向内存中其他地方的某个布尔值的指针,这就是值发生变化的地方。但是你的变量——现在是一个带有@State的指针——不会改变,总是指向内存中的那个地方。

注意:- 接受的答案是正确的,但如果你想寻找更简单的解释,我在下面尝试过


@State 属性 包装器允许我们更改结构内的值。

注意:- 您不能将结构中的 属性 更改为其值类型,因此不允许。

struct ExampleTextView: View {

    // Declare a variable with state property wrapper
    @State private var shouldChangeText: Bool = false
    
    var body: some View {
        Text("Just an example")
            .foregroundColor(Color.white)
    }
}
  • 如果您想知道我们是否应该添加私有访问说明符?

    是的,根据经验苹果建议不应该使用@State 属性 与其他视图共享,因为有更具体的 属性 包装器 @ObservedObject 和@EnvironmentObject.

  • 但如果它是值类型,如何改变它存储在哪里?

    所以每当我们用@State标记一个属性时,我们就把它的存储移出 从结构到 SwiftUI.

    管理的共享存储

以防万一,如果你想与Swift进行比较,那么它就是这样做的,

struct Example {
    var exampleType: String
    
    mutating func changeType() {
        exampleType = "Are we allowed to do this?"
    }
}

来源:请注意此答案的灵感来自此 post https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper