iOS SwiftUI 创建和组合视图 3.1
第四节 使用可观察对象来存储数据
要实现用户标记哪个地标为自己喜爱的地标这个功能,需要使用可观察对象(observalble object
)存放地标数据
可观察对象是一种可以绑定到具体SwifUI视图环境中的数据对象。SwiftUI
可以察觉它影响视图展示的任何变化,并在这种变化发生后及时更新对应视图的展示内容
步骤1 创建一个名为UserData.swift
的文件
步骤2 声明一个遵循ObservableObject
协议的新数据模型,ObservableObject
协议来自响应式框架Combine
。SwiftUI可以订阅可观察对象,并在数据发生改变时更新视图的显示内容
步骤3 添加存储属性showFavoritesOnly
和landmarks
,并赋予初始值。可观察对象需要对外公布内部数据的任何改动,因此订阅此可观察对象的订阅者就可以获得对应的数据改动信息
步骤4 给新建的数据模型的每一个属性添加@Published
属性修饰词
第五节 视图中适配数据模型对象
已经创建了UserData
可观察对象,现在要改造视图,让它使用这个新的数据模型来存储视图内容数据
步骤1 在LandmarkList.swift
文件中,使用@EnvironmentObject
修饰的userData
属性来替换原来的showFavoritesOnly
状态属性,并对预览视图调用environmentObject(_:)
修改器。只要environmentObject(_:)
修改器应用在视图的父视图上,userData
就能够自动获取它的值。
步骤2 替换原来使用showFavoritesOnly
状态属性的地方,改为使用userData
中的对应属性。与@State
修饰的属性一样,也可以使用$
前缀访问userData
对象的成员绑定引用
步骤3 创建ForEach
实例时使用userData.landmarks
做为数据源
步骤4 在SceneDelegate.swift
中,对LandmarkList
视图调用environmentObject
修改器,这样可以把UserData
的数据对象绑定到LandmarkList
视图的环境变量中,子视图可以获得父视图环境中的变量。此时如果在模拟器或者真机上运行应用,也可以正常展示视图内容
步骤5 更新LandmarkDetail
视图,让它从父视图的环境变量中取要展示的数据。之后在更新地标的用户喜爱状态时,会用到landmarkIndex
这个变量
步骤6 切换到LandmarkList.swift
文件,并打开实时预览视图去验证所添加的功能是否正常工作
第六节 为每一个地标创建一个喜爱按钮
Landmark
这个应用可以在喜欢和不喜欢的地标列表间进行切换了,但喜欢的地标列表还是硬编码形成的,为了让用户可以自己标记哪个地标是自己喜欢的,需要在地标详情页添加一个标记喜欢的按钮
步骤1 在LandmarkDetail.swift
的HStack
中添加地标名称的Text
步骤2 在地标名称的Text
控件旁边添加一个新的按钮控件。使用if-else
条件语句设置不同的图片显示状态表示这个地标是否被用户标记为喜欢。在Button
的动作闭包中,使用了landmarkIndex
去修改userData
中对应地标的数据。
步骤3 切换到landmarkList.swift
,并开启实时预览模式。当从列表页导航进入详情页后,点击喜欢按钮,喜欢的状态会在返回列表页后与列表中对应的地标喜欢状态保持一致,因为列表页和详情页的地标数据使用的是同一份,所以可以在不同页面间保持状态同步。
检查是否理解
问题1 下列选项哪个可以把数据按视图层级关系传递下去?
-
@EnvironmentObject
属性 -
environmentObject(_:)
修改器
问题2 绑定(binding)的作用是什么?
- 绑定是值和改变值的方法
- 是一个视图连接在一起的方法,确保连续起来的视图接收同一份数据
- 是一个临时固化值的方式,目的是在其它视图状态变化时,保持值不改变