SwiftUI教程 使用@State
关键字表示可变的UI状态:
@State var showFavoritesOnly = false
它提供了以下摘要:
State是一个值或一组值,可以随时间而改变,并影响视图的行为、内容或布局。使用具有@State属性的属性向视图添加状态。
- 这个关键字到底是什么意思?
- 如何通过修改
@State
变量来触发视图重新计算? body
getter中的其他变量如何是不可变的?
SwiftUI教程 使用@State
关键字表示可变的UI状态:
@State var showFavoritesOnly = false
它提供了以下摘要:
State是一个值或一组值,可以随时间而改变,并影响视图的行为、内容或布局。使用具有@State属性的属性向视图添加状态。
@State
变量来触发视图重新计算?body
getter中的其他变量如何是不可变的?@State
关键字是一个@propertyWrapper
,这是Swift 5.1中最近引入的一项功能。正如相应的提案所解释的那样,它是一种值包装器,避免了样板代码。
附注:@propertyWrapper
以前被称为@propertyDelegate
,但自那时以来已经改变了。有关更多信息,请参见此帖子。
官方@State文档有以下内容:
SwiftUI
管理您声明为状态的任何属性的存储。 当状态值更改时,视图将失效并重新计算主体。将状态用作给定视图的单一真相来源。状态实例不是值本身;它是读取和修改值的一种手段。要访问状态的基础值,请使用其值属性。
因此,当你初始化一个标记为@State
的属性时,你实际上并没有创建自己的变量,而是促使SwiftUI
在后台创建一个"something"来存储你设置的内容,并从现在开始监控它!你的@State var
只是作为访问这个包装器的委托。
每次你写入@State
变量时,SwiftUI
会知道,因为它正在监视它。它还会知道是否从View
的body
中读取了@State
变量。利用这些信息,它将能够重新计算引用了body
中@State
变量的任何View
,在这个变量发生变化后。
@propertyWrapper
更受欢迎。 - fredpi@propertyWrapper
,它是一个包装器,不仅知道何时被写入,也知道何时被读取 - 这样,它可以确定从哪些视图中读取。我在我的回答中添加了关于此的说明。 - fredpi如果您熟悉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: '',
};
}
}
props
对象。因为它们都来自于它们的父控件/组件。 - s1ro6在WWDC视频-204会议中有一个很好的例子来解释它(从16:00开始,引文起始于20:15)。
@State
变量的特殊属性之一是SwiftUI可以观察它们何时被读取和写入。因为SwiftUI知道zoomed
在body
中被读取,所以它知道视图的渲染取决于它。这意味着当一个变量发生改变时,框架将使用新的@State
值再次请求body
。
SwiftUI中的数据流程(5:38)也详细阐述和证明了作为属性包装器的@State
。它展示了如何解决我们在一个不可变的(struct
)View
中需要一个可变值的问题。
body
以获取全新生成的界面。 - matt如果您点击进入@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
@State
与x:Bind
或Binding
非常相似,甚至可以说是一样的。在集合上,它与ObservableCollection
非常相似,甚至可以说是一样的。@State
属性委托来监听变量的更新。