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



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

@State var showFavoritesOnly = false

它提供了以下摘要:

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

  • 关键字到底是什么意思?
  • 更改@State变量如何导致重新计算视图?
  • 其他变量在bodygetter中是如何不可变的?

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


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


官方@State文档有以下几点要说:

SwiftUI管理您声明为状态的任何属性的存储当状态值更改时,视图将使其外观无效,并且 重新计算正文。使用状态作为 给定视图。

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

因此,当您初始化标记为@State的属性时,您实际上并不是在创建自己的变量,而是提示SwiftUI在后台创建"某些东西">来存储您设置的内容并从现在开始监控它!您的@State var只是充当访问此包装器的委托

每次写入@State变量时,SwiftUI都会知道它正在监视它。它还将知道@State变量是否是从Viewbody中读取的。使用此信息,它将能够在更改@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属性包装器存储的值由CombineCurrentValueSubject管理。 顾名思义,这实质上存储当前值,然后可以使用$语法将其用作可绑定属性。

我喜欢斯坦福大学的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开发。@Statex:BindBinding不同,即使不同,也是相似的。在集合上,它与ObservableCollection相似,如果不同。

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

最新更新