文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SwiftUI 属性包装器如何处理结构体

2024-12-02 15:48

关注

本文转载自微信公众号「网罗开发」,作者韦弦Zhy。转载本文请联系网罗开发公众号。

已经了解了 SwiftUI 如何通过使用 @State 属性包装器将变化的数据存储在结构体中,如何使用 $ 将状态绑定到UI控件的值,以及更改 @state 包装的属性时是如何自动让 SwiftUI 重新调用我们的结构体的 body属性的。

所有这些结合在一起,使我们可以编写如下代码:

  1. struct ContentView: View { 
  2.     @State private var blurAmount: CGFloat = 0 
  3.  
  4.     var body: some View { 
  5.         VStack { 
  6.             Text("Hello, World!"
  7.                 .blur(radius: blurAmount) 
  8.  
  9.             Slider(value: $blurAmount, in: 0...20) 
  10.         } 
  11.     } 

如果您执行这些代码,将会发现左右拖动滑块可以完全按照预期调整文本标签的模糊量。

现在,假设我们希望该绑定不仅仅是处理模糊效果的半径。也许我们想将其保存到 UserDefaults 中,运行一个方法,或者只是打印出该值以进行调试。您可以尝试像这样更新属性:

  1. @State private var blurAmount: CGFloat = 0 { 
  2.     didSet { 
  3.         print("New value is \(blurAmount)"
  4.     } 

如果您运行该代码,您将感到失望:当您拖动滑块周围时,您会看到模糊量的变化,但是您不会看到我们的 print() 语句被触发——实际上,什么都不会输出。

为了了解这里发生的事情,我希望您考虑一下我们在使用 Core Data 时:我们使用 @FetchRequest 属性包装器查询我们的数据,但我还向您展示了如何直接使用 FetchRequest 结构体,以便我们可以更好地控制它是如何创建的。

属性包装器具有该名称,因为它们将我们的属性包装在另一个结构体中。对于许多属性包装器而言,该结构体与包装器本身具有相同的名称,但是使用 @FetchRequest 时我向您展示了我们实际上是如何实际读取其中的包装值——获取的结果,而不是请求本身。

这意味着当我们使用 @State 来包装字符串时,最终得到的实际属性类型是 State。类似地,当我们使用 @Environment 和其他环境时,我们最终得到一个 Environment 类型的结构体,该结构体内部包含一些其他值。

之前我曾解释说,我们无法在视图中修改属性,因为它们是结构体,因此是固定的。但是,现在您知道 @State 本身会生成一个结构体,因此我们面临一个难题:如何修改该结构体?

Xcode 有一个非常有用的命令,称为“快速打开”(使用 Cmd + Shift + O 进行访问),该命令使您可以在项目或已导入的任何框架中找到任何文件或类型。现在将其激活,然后输入 "State"——希望第一个结果在其下方显示 SwiftUI,但如果没有,请找到并选择它。

您将进入 SwiftUI 生成的界面,该界面实质上是 SwiftUI 向我们展示的所有的部分。那里没有实现代码,只有协议,结构体,修饰符等的许多定义。

我们要求查看 state,因此您应该被带到此行:

  1. @propertyWrapper public struct State : DynamicProperty { 

该 @propertyWrapper 属性使它成为 @State 供我们使用。

现在往下看几行,您应该看到以下内容:

  1. public var wrappedValue: Value { get nonmutating set } 

该包装值是我们要存储的实际值,例如字符串。这个生成的接口告诉我们,该属性可以读取(get)和写入(set),但是当我们设置该值时,它实际上不会更改结构体本身。在后台,它将值发送给SwiftUI以便存储在可以自由修改的位置,因此,结构体本身永不改变。

现在您已经知道了所有这些,让我们回到我们的问题代码:

  1. @State private var blurAmount: CGFloat = 0 { 
  2.  
  3. didSet { 
  4.  
  5. print("New value is \(blurAmount)"
  6.  
  7.  

在表面上,状态为“ 当blurAmount 更改时,打印出它的新值。”但是,由于 @State 实际上会包装其内容,因此实际上是说,当包装 blurAmount 的 State 结构体更改时,请打印出新的模糊量。

还在这儿?现在让我们更进一步:您已经看到 State 如何使用一个非可变的 setter 包装其值,这意味着 blurAmount 或包装它的 State 结构体都没有改变——我们的绑定直接改变了内部存储的值,这意味着属性观察者永远不会被触发。

那么我们该如何解决——我们如何将一些功能附加到包装的属性上?为此,我们需要自定义绑定——让我们接下来看看...

> 译自 How property wrappers become structs[1]

参考资料

[1]How property wrappers become structs: https://www.hackingwithswift.com/books/ios-swiftui/how-property-wrappers-become-structs

 

来源: 网罗开发内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯