54

SwiftUI教程使用@State关键字来表示可变的 UI 状态:

@State var showFavoritesOnly = false

它提供了以下摘要:

状态是一个值或一组值,可以随时间变化,并影响视图的行为、内容或布局。您可以使用带有 @State 属性的属性来向视图添加状态。

  • 关键字究竟是什么意思?
  • 变异变量如何@State导致重新计算视图?
  • bodygetter中的其他变量如何不可变?
4

7 回答 7

60

@State关键字是 a ,这@propertyWrapper是最近在 Swift 5.1 中引入的一个特性。正如相应提案中所解释的,它是一种避免样板代码的值包装器。


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


@State官方文档有以下内容:

SwiftUI 管理您声明为状态的任何属性的存储。 当状态值改变时,视图使其外观无效并重新计算 body。使用状态作为给定视图的唯一真实来源。

State 实例不是值本身;这是一种读取和改变 value 的方法。要访问一个状态的基础值,请使用它的 value 属性。

因此,当您初始化一个标记为 的属性时@State,您实际上并没有创建自己的变量,而是提示在后台SwiftUI创建“某物”来存储您设置的内容并从现在开始对其进行监控!你@State var只是作为一个代表来访问这个 wrapper

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

于 2019-06-04T07:08:36.700 回答
6

WWDC 视频中的示例很好地解释了它- Session 204(从 16:00 开始,报价从 20:15 开始)

变量的特殊属性之一@State是 SwiftUI 可以观察它们何时被读取和写入。因为 SwiftUI 知道它zoomed被读入body,所以它知道视图的渲染依赖于它。这意味着 - 当变量更改时,框架将body再次要求使用新@State值。

作为@State属性包装器也在Data Flow Through Swift UI (5:38) WWDC 视频中进行了详细说明和证明。struct它展示了当我们需要不可变 ( )中的可变值时它如何解决问题View

于 2019-06-05T14:20:14.667 回答
5

如果你知道 React Native,让我补充一点。

该属性与 React Native 中@State的对象非常相似。this.state

例如:

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

当您修改用户名变量时,它们将具有相同的效果,即重新呈现当前页面。

于 2019-06-06T08:01:03.563 回答
3

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

于 2019-06-16T04:23:23.680 回答
1

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

于 2021-05-19T04:37:23.230 回答
0

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


@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?"
    }
}

信用:请注意,这个答案的灵感来自这篇文章https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper

于 2021-10-09T19:30:29.890 回答
0

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

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

于 2019-06-04T14:06:28.760 回答