SwiftUI之深入解析属性包装器如何处理结构体
- 已经了解了 SwiftUI 如何通过使用 @State 属性包装器将变化的数据存储在结构体中,如何使用 $ 将状态绑定到 UI 控件的值,以及更改 @state 包装的属性时是如何自动让 SwiftUI 重新调用结构体的 body 属性的。
- 所有这些结合在一起,可以编写如下代码:
struct ContentView: View {@State private var blurAmount: CGFloat = 0var body: some View {VStack {Text("Hello, World!").blur(radius: blurAmount)Slider(value: $blurAmount, in: 0...20)}}
}
- 如果执行这些代码,将会发现左右拖动滑块可以完全按照预期调整文本标签的模糊量。现在,假设我们希望该绑定不仅仅是处理模糊效果的半径,想将其保存到 UserDefaults 中,运行一个方法,或者只是打印出该值以进行调试,可以尝试像这样更新属性:
@State private var blurAmount: CGFloat = 0 {didSet {print("New value is \(blurAmount)")}
}
- 如果运行该代码,可能会出现失望的结果:当拖动滑块周围时,会看到模糊量的变化,但是不会看到我们的 print() 语句被触发,实际上什么都不会输出。
- 为了了解这里的原因,可以考虑一下在使用 Core Data 时:使用 @FetchRequest 属性包装器查询我们的数据,以及如何直接使用 FetchRequest 结构体,以便可以更好地控制它是如何创建的。
- 属性包装器具有该名称,因为它们将我们的属性包装在另一个结构体中。对于许多属性包装器而言,该结构体与包装器本身具有相同的名称,但是使用 @FetchRequest 时展示了实际上是如何实际读取其中的包装值,获取的结果,而不是请求本身。
- 这意味着当使用 @State 来包装字符串时,最终得到的实际属性类型是 State。类似地,当使用 @Environment 和其他环境时,我们最终得到一个 Environment 类型的结构体,该结构体内部包含一些其他值。
- 之前曾解释说,我们无法在视图中修改属性,因为它们是结构体,因此是固定的。但是,现在知道 @State 本身会生成一个结构体,因此面临一个难题:如何修改该结构体?
- Xcode 有一个非常有用的命令,称为“快速打开”(使用 Cmd + Shift + O 进行访问),该命令可以在项目或已导入的任何框架中找到任何文件或类型。现在将其激活,然后输入 “State”,希望第一个结果在其下方显示 SwiftUI,但如果没有,请找到并选择它:
- 将进入 SwiftUI 生成的界面,该界面实质上是 SwiftUI 向我们展示的所有的部分。那里没有实现代码,只有协议,结构体,修饰符等的许多定义。
- 我们可以查看 state,因此应该被带到此行:
@propertyWrapper public struct State<Value> : DynamicProperty {
- 该 @propertyWrapper 属性使它成为 @State 供我们使用,现在往下看几行,可以看到以下内容:
public var wrappedValue: Value { get nonmutating set }
- 该包装值是我们要存储的实际值,例如字符串,这个生成的接口告诉我们,该属性可以读取(get)和写入(set),但是当设置该值时,它实际上不会更改结构体本身。在后台,它将值发送给SwiftUI以便存储在可以自由修改的位置,因此,结构体本身永不改变。
- 现在知道了所有这些,让我们回到问题代码:
@State private var blurAmount: CGFloat = 0 {didSet {print("New value is \(blurAmount)")}
}
- 在表面上,状态为“ 当blurAmount 更改时,打印出它的新值”。但是,由于 @State 实际上会包装其内容,因此实际上是说,当包装 blurAmount 的 State 结构体更改时,请打印出新的模糊量。
- 还在这儿?现在让我们更进一步:已经看到 State 如何使用一个非可变的 setter 包装其值,这意味着 blurAmount 或包装它的 State 结构体都没有改变,我们的绑定直接改变了内部存储的值,这意味着属性观察者永远不会被触发。
SwiftUI之深入解析属性包装器如何处理结构体相关推荐
- Swift Property Wrapper 属性包装器
@propertyWrapper属性包装器:在定义存储属性时添加一个分离层,代表该属性被包装起来,且在包装器内部可以做一些事情.把一些通用复用的代码放在了包装器中,比如线程安全检查或者数据存储到数据库 ...
- 深入解析JNA—模拟C语言结构体
原帖:http://blog.csdn.net/shendl/article/details/3599849 深入解析JNA-模拟C语言结构体 前言 前几天写<JNA--JNI终结者>一文 ...
- SwiftUI之深入解析@StateObject、@ObservedObject和@EnvironmentObject的联系和区别
一.@State 属性包装器 ① 什么是 @State 属性包装器? 状态在任何现代应用程序中都是不可避免的,但在 SwiftUI 中,重要的是所有的视图都是它们状态的简单函数,我们不需要直接改变视图 ...
- NSValue包装自定义结构体
typedef struct {int year;int month;int day; }Date;void value(){Date date = {2013,9,30},//void *代表任何类 ...
- SwiftUI之深入解析如何处理特定的数据和如何在视图中适配数据模型对象
一.前言 阅读了我的前两篇博客的朋友,应该都熟练掌握了 SwiftUI 如何创建一个任何相关信息的展示视图和各个视图之间的相互组合,以及动态生成一个展示相关信息的可滚动列表,用户可以点击列表项去查看其 ...
- SwiftUI之深入解析如何创建列表展示视图和列表如何导航跳转新页面
一.前言 地标详情页视图已经创建完成,我们需要提供一种方式让用户可以查看完整的地标列表,并且可以查看每一个地标的详情.地标详情页视图的创建,请参考我的博客:SwiftUI之深入解析如何创建和组合视图. ...
- 【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
文章目录 I . 属性 字段 总结 II . 属性声明 III . 属性初始化器 IV . get / set 属性访问器 V . 属性幕后字段 field VI . 变量和常量的区别 VII . 延 ...
- java包装器类_Java中的基本类型和包装类
Java中基本数据类型与包装类型有 基本类型 包装器类型 boolean Boolean char Character int Integer byte Byte short Short long L ...
- SwiftUI之深入解析高级动画的几何效果GeometryEffect
一.前言 在我的博客 SwiftUI之深入解析高级动画的路径Paths 中,已经了解了 Animatable 的协议,以及如何使用它来动画路径.接下来,我们将使用相同的协议来动画变换矩阵,使用一个新的 ...
最新文章
- android升级gradle到3.4.1
- 消防验收找问题,一般就是这些了!
- 018.Zabbix维护时间和模板导入
- GitHub 发布了一款重量级产品,可直接运行代码
- Google Guava多集
- 攻防世界 适合做桌面_空间“狭小”的二人世界,适合情侣们做浪漫的事情
- 基于阿里云ECS+ 宝塔面板(bt) + WordPress 搭建个人主页(以独立博客为例)
- bzoj千题计划227:bzoj1486: [HNOI2009]最小圈
- Web浏览器已经限制此文件显示
- java网上在线考试系统代码_Java+JavaWeb在线考试系统
- 知网下载论文CAJ格式转为PDF格式
- uni-app 无网络图标不显示问题解决
- 一加七pro计算机没有记录了,尽享速度与激情:一加7T Pro 迈凯伦版评测
- C++基础面试问题总结
- GPS GLONASS数据文件类型解析
- 区块链技术应用将迎来多场景布局
- ipad显示连接不到商店服务器,iPad无法连接App Store 打不开怎么办
- PS出现“不能完成存储为命令,因为没有足够的内存RAM” 设置性能时“要求96和8之间的整数。已插入最接近的数值”
- UVALive 4394 String painter——dp
- 【蓝桥杯嵌入式备赛】10.拓展板数码管、ADC按键及光敏电阻