SwiftUI `@State` 关键字有啥作用?
Posted
技术标签:
【中文标题】SwiftUI `@State` 关键字有啥作用?【英文标题】:What does the SwiftUI `@State` keyword do?SwiftUI `@State` 关键字有什么作用? 【发布时间】:2019-10-19 16:18:51 【问题描述】:SwiftUI tutorial 使用 @State
关键字来指示可变的 UI 状态:
@State var showFavoritesOnly = false
它提供了以下摘要:
关键字究竟是什么意思? 改变状态是一个值或一组值,它可以随时间变化,并影响视图的行为、内容或布局。您可以使用带有 @State 属性的属性来向视图添加状态。
@State
变量如何导致重新计算视图?
body
getter 中的其他变量如何不可变?
【问题讨论】:
这是全新的,我认为在 WWDC 期间将提供更多信息或进一步解释,所以我不明白为什么这么急于发布有关 SwiftUI 的问题,即使我了解很多渴望开始探索它。 @JoakimDanielson 这是个坏问题吗? 这在某种程度上是我的观点,也许这是一个好问题,也许不是。很难说,因为这都是新事物。 好吧,我真的很好奇这是如何实现的以及需要添加哪些语言功能。 @JoakimDanielson 你不能指望没有人问关于新技术的问题 【参考方案1】:@State
关键字是 @propertyWrapper
,这是最近在 Swift 5.1 中引入的功能。正如corresponding proposal 中所解释的,它是一种避免样板代码的值包装器。
旁注:@propertyWrapper
以前被称为 @propertyDelegate
,但后来发生了变化。请参阅this post 了解更多信息。
official @State documentation 有以下说法:
SwiftUI
管理您声明为状态的任何属性的存储。 当状态值改变时,视图使其外观无效,并且 重新计算身体。使用状态作为单一事实来源 给定的观点。State 实例不是值本身;这是一种手段 读取和改变值。要访问一个州的潜在价值, 使用它的 value 属性。
因此,当您初始化标记为 @State
的属性时,您实际上并没有创建自己的变量,而是提示 SwiftUI
在后台创建 "something" 来存储您的内容从现在开始设置并监控它!您的@State var
只是作为代表来访问此包装器。
每次您的@State
变量被写入 时,SwiftUI
都会知道,因为它正在监视它。它还将知道@State
变量是否是从View
的body
中读取的。使用此信息,它将能够重新计算在更改此变量后在其 body
中引用了 @State
变量的任何 View
。
【讨论】:
它们仍然被称为属性委托还是现在是属性包装器?也许两者都有:( 这是很好的信息,但这实际上是如何工作的:“当状态值发生变化时,视图使其外观无效并重新计算主体”?在 Integrating 视频中,意大利人说 SwiftUI 知道 state 属性在 body 中使用,它也知道它在哪个视图中。我不明白这怎么可能,是吗? @23inhouse 我已在我的帖子中对此进行了澄清。 TLDR:它们的意思相同,但首选@propertyWrapper
。
@Gusutafu @propertyWrapper
是一个包装器,它不仅知道何时写入,还知道何时读取——这样,它就可以确定从哪些视图读取。我已在回答中对此进行了澄清。【参考方案2】:
WWDC video - Session 204 中的示例很好地解释了它(从 16:00 开始,报价从 20:15 开始)
@State
变量的一个特殊属性是 SwiftUI 可以观察它们何时被读取和写入。因为 SwiftUI 知道zoomed
是在body
中读取的,所以它知道视图的渲染依赖于它。这意味着 - 当变量更改时,框架将使用新的@State
值再次请求body
。
@State
作为属性包装器也在Data Flow Through Swift UI (5:38) WWDC 视频中进行了详细说明和证明。它展示了当我们需要不可变 (struct
) View
中的可变值时,它如何解决问题。
【讨论】:
“因为 SwiftUI 知道 zoomed 是在正文中读取的” - Swift 中的什么机制使这成为可能? @Gusutafu 组合框架(发布和订阅)。 SwiftUI 提供订阅者,因此每次发布者发出变量已更改的消息时,它都会听到。作为响应,它调用body
来重新生成接口。
谢谢,但我一直在努力解决的问题是 如何 SwiftUI 或 State 本身可能知道 State 被用于特定身体!【参考方案3】:
如果你知道 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: '',
;
当您修改用户名变量时,它们将具有相同的效果,即重新呈现当前页面。
【讨论】:
【参考方案4】:如果你点击@State
,你可以看到它有几个getter。一个是Value
,另一个是Binding<Value>
。
SwiftUI 似乎在很大程度上依赖于响应式编程(以及他们新的 Combine
框架,并且由于我们看不到这些包装器的完整实现,我希望通过 @State
属性包装器存储的值由 @ 管理987654326@ 来自Combine
。顾名思义,这实际上存储了当前值,然后可以使用$
语法将其用作可绑定属性。
【讨论】:
【参考方案5】:我喜欢斯坦福大学的 Paul Hegarty 教授的解释。他说@State 基本上将该变量转换为指向内存中其他位置的某个布尔值的指针,这就是值发生变化的地方。但是你的变量——现在是一个带有@State 的指针——并没有改变,总是指向内存中的那个地方。
【讨论】:
【参考方案6】:如果您了解 C# 和 Windows 开发。 @State
与 x:Bind
或 Binding
不同时相似。在集合上,与 ObservableCollection
不同时相似。
正如 fredpi 所说,SwiftUI 正在列出带有 @State
属性委托的 vars 更新。
【讨论】:
【参考方案7】:注意:- 接受的答案是正确的,但如果您试图寻找我在下面尝试过的更简单的解释
@State 属性包装器允许我们更改结构内的值。
注意:- 您不能将结构中的属性更改为 a 值类型,因此不允许。
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)
如果您想知道我们是否应该添加私有访问说明符?
是的,根据经验,Apple 建议不应使用 @State 属性 与其他视图共享,因为有更具体的属性包装器 @ObservedObject 和 @EnvironmentObject。
但如果它是值类型,那么如何改变它存储在哪里呢?
因此,每当我们使用@State 标记属性时,我们都会将其存储移出 从 struct 到 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
【讨论】:
以上是关于SwiftUI `@State` 关键字有啥作用?的主要内容,如果未能解决你的问题,请参考以下文章
通过更改 SwiftUI 中的 @State 变量来刷新视图不起作用
sklearn的ParameterSampler中的random_state参数有啥作用?