在Swift / SwiftUI中,美元符号有什么作用?

67

这篇由苹果公司关于SwiftUI的教程使用美元符号来绑定数据,我在寻找更多关于SwiftUI中数据绑定的信息时遇到了困难。

Toggle(isOn: $showFavoritesOnly) {

你可以使用$前缀来访问状态变量的绑定或者它的属性。
这是一种类似于inout类型参数的东西吗?它使用&符号进行传递。

7
抱歉,我没有这么做。我原以为应该先从SwiftUI入手,并且认为这个美元符号已经在Swift中了,所以我没有去查阅Swift的相关内容。没必要这么强硬。 - vrwim
2个回答

89

在WWDC 2019视频415中,这个问题解释得非常清楚。您只是看到了一种广泛的语言特性中的一个特殊情况,即属性包装器。

属性包装器(例如@State)实际上是引用具有相同名称(例如State)的类型实例(通常为结构体或枚举类型)的一种方式。后者提供了将此实例属性转换为计算属性的说明,其getter和setter是其自身的某个计算属性(其wrappedValue)。它还通常保存支持该计算属性的私有存储。

因此,在声明之后,

@State var showFavoritesOnly = true

showFavoritesOnly被转换为计算属性,其getter和setter由State结构提供。当您将showFavoritesOnly设置为true时,它会通过State结构的setter进行路由,并最终进入State实例的存储属性。

所有这些都意味着在某处与您的showFavoritesOnly相关联的存在一个State实例。确实如此,但它被隐藏了起来。如果您想看到该State实例的名称,则为_showFavoritesOnly

但是,当您说$showFavoritesOnly时,您并没有得到一个State结构;您得到一个Binding结构。为什么?因为属性包装器具有指定从$名称返回值的机制。对于State而言,它指定该值应为其自己的binding属性,该属性是Binding(请参阅文档:https://developer.apple.com/documentation/swiftui/state)。

出乎巧合的是,Toggle的isOn初始化程序采用了绑定(再次参见文档:https://developer.apple.com/documentation/swiftui/toggle/3232112-init)。即使您想,也无法将Toggle的isOn设置为showFavoritesOnly!相反,您将其设置为State实例提供的Binding<Bool>,以便Toggle与State对象自动进行双向通信。SwiftUI框架强制执行其自己的正确使用;Toggle仅可以存在于某个绑定的关系中,该绑定作为其开/关状态的基础真相源。由于它是绑定而不是普通的布尔值,因此通信可以在两个方向上工作:当用户在Toggle中点击开关时,值的更改会通过绑定传递“向上”至State变量。


4
好的!参考视频在这里:https://developer.apple.com/videos/play/wwdc2019/415/ - Robert Monfera
3
具体来说,讲解中的属性包装器部分从23:30开始。 - Robert Monfera

49

$ 与属性包装器(以前称为“property delegates”)一起使用。

不是运算符,而是一个前缀(感谢 @matt!)。

有关属性包装器的更多信息,请参阅此Swift Evolution 文档

例如,在@State var aState = false中,State是一个属性包装器。

这意味着如果我们写:

  • aState,我们正在访问一个Bool
  • $aState,我们正在访问一个Binding<Bool>

不同的属性包装器将生成不同的值,称为“projected values”。


17
你的说法让它听起来像某种运算符,但实际上并不是。美元符号只是变量名的第一个字母而已,并不会“创建”绑定。$aState 才是真正的绑定。 - matt
“Binding”的值应该是“projectedValue”,对吗? - Itachi
文档中还有一个不错的例子,位于 https://docs.swift.org/swift-book/LanguageGuide/Properties.html 的“从属性包装器中投射值”章节。 - DanSkeel
@Itachi 是的,@State 属性包装器的 projectedValue 具有类型 Binding - DanSkeel
1
我现在看到了 @State@Binding 变量中的 _aState,这是什么意思?据我所知,下划线与美元符号的作用相同。 - vrwim
"projectedValue是使用$运算符访问的属性。'operator'是什么?" - Paweł Brewczynski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接