SwiftUI 教程使用@State
关键字来指示可变的 UI 状态:
@State var showFavoritesOnly = false
它提供了以下摘要:
状态是一个值或一组值,可以随时间变化,并影响视图的行为、内容或布局。使用具有 @State 属性的属性向视图添加状态。
- 关键字到底是什么意思?
- 更改
@State
变量如何导致重新计算视图? - 其他变量在
body
getter中是如何不可变的?
@State
关键字是一个@propertyWrapper
,这是最近在 Swift 5.1 中引入的一个功能。正如相应的提案中所解释的,它是一种避免样板代码的值包装器。
旁注:@propertyWrapper
以前被称为@propertyDelegate
,但后来发生了变化。有关更多信息,请参阅此帖子。
官方@State文档有以下几点要说:
SwiftUI
管理您声明为状态的任何属性的存储。当状态值更改时,视图将使其外观无效,并且 重新计算正文。使用状态作为 给定视图。State 实例不是值本身;它是一种 读取和改变值。要访问状态的基础值, 使用其值属性。
因此,当您初始化标记为@State
的属性时,您实际上并不是在创建自己的变量,而是提示SwiftUI
在后台创建"某些东西">来存储您设置的内容并从现在开始监控它!您的@State var
只是充当访问此包装器的委托。
每次写入@State
变量时,SwiftUI
都会知道它正在监视它。它还将知道@State
变量是否是从View
的body
中读取的。使用此信息,它将能够在更改@State
变量后重新计算在其body
中引用了该变量的任何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: '',
};
}
}
当您修改用户名变量时,它们将具有相同的效果,即重新呈现当前页面。
WWDC视频中的一个例子很好地解释了它 - 会话204(从16:00开始,报价从20:15开始)
@State
变量的特殊属性之一是 SwiftUI 可以观察它们何时被读取和写入。因为 SwiftUI 知道zoomed
是在body
中读取的,所以它知道视图的呈现依赖于它。这意味着 - 当变量更改时,框架将使用新的@State
值再次请求body
。
作为属性包装器@State
在Data Flow Through Swift UI(5:38)WWDC vid中也有详细说明和证明。它展示了当我们需要在不可变(struct
)View
中可变值时如何解决问题。
如果你点击进入@State
你可以看到它有几个getter。 一个与Value
另一个与Binding<Value>
. SwiftUI 似乎严重依赖响应式编程(及其新的Combine
框架,并且由于我们看不到这些包装器的完整实现,我希望通过@State
属性包装器存储的值由Combine
CurrentValueSubject
管理。 顾名思义,这实质上存储当前值,然后可以使用$
语法将其用作可绑定属性。
我喜欢斯坦福大学的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?"
}
}
信用:请注意,这个答案的灵感来自这篇文章 https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper
如果你了解C#和Windows开发。@State
与x:Bind
或Binding
不同,即使不同,也是相似的。在集合上,它与ObservableCollection
相似,如果不同。
正如 fredpi 所说,SwiftUI 正在列出带有@State
属性委托的变量更新。