注册

iOS SwiftUI 创建和组合视图 3.1

第四节 使用可观察对象来存储数据

要实现用户标记哪个地标为自己喜爱的地标这个功能,需要使用可观察对象(observalble object)存放地标数据

可观察对象是一种可以绑定到具体SwifUI视图环境中的数据对象。SwiftUI可以察觉它影响视图展示的任何变化,并在这种变化发生后及时更新对应视图的展示内容

observable

步骤1 创建一个名为UserData.swift的文件

步骤2 声明一个遵循ObservableObject协议的新数据模型,ObservableObject协议来自响应式框架Combine。SwiftUI可以订阅可观察对象,并在数据发生改变时更新视图的显示内容

步骤3 添加存储属性showFavoritesOnlylandmarks,并赋予初始值。可观察对象需要对外公布内部数据的任何改动,因此订阅此可观察对象的订阅者就可以获得对应的数据改动信息

步骤4 给新建的数据模型的每一个属性添加@Published属性修饰词

combine

第五节 视图中适配数据模型对象

已经创建了UserData可观察对象,现在要改造视图,让它使用这个新的数据模型来存储视图内容数据

model

步骤1 在LandmarkList.swift文件中,使用@EnvironmentObject修饰的userData属性来替换原来的showFavoritesOnly状态属性,并对预览视图调用environmentObject(_:)修改器。只要environmentObject(_:)修改器应用在视图的父视图上,userData就能够自动获取它的值。

步骤2 替换原来使用showFavoritesOnly状态属性的地方,改为使用userData中的对应属性。与@State修饰的属性一样,也可以使用$前缀访问userData对象的成员绑定引用

步骤3 创建ForEach实例时使用userData.landmarks做为数据源

envrionment object

步骤4 在SceneDelegate.swift中,对LandmarkList视图调用environmentObject修改器,这样可以把UserData的数据对象绑定到LandmarkList视图的环境变量中,子视图可以获得父视图环境中的变量。此时如果在模拟器或者真机上运行应用,也可以正常展示视图内容

scene delegate

步骤5 更新LandmarkDetail视图,让它从父视图的环境变量中取要展示的数据。之后在更新地标的用户喜爱状态时,会用到landmarkIndex这个变量

landmark detail environment

步骤6 切换到LandmarkList.swift文件,并打开实时预览视图去验证所添加的功能是否正常工作

landmark list environment

第六节 为每一个地标创建一个喜爱按钮

Landmark这个应用可以在喜欢和不喜欢的地标列表间进行切换了,但喜欢的地标列表还是硬编码形成的,为了让用户可以自己标记哪个地标是自己喜欢的,需要在地标详情页添加一个标记喜欢的按钮

favorite button

步骤1 在LandmarkDetail.swiftHStack中添加地标名称的Text

步骤2 在地标名称的Text控件旁边添加一个新的按钮控件。使用if-else条件语句设置不同的图片显示状态表示这个地标是否被用户标记为喜欢。在Button的动作闭包中,使用了landmarkIndex去修改userData中对应地标的数据。

favorite star button

步骤3 切换到landmarkList.swift,并开启实时预览模式。当从列表页导航进入详情页后,点击喜欢按钮,喜欢的状态会在返回列表页后与列表中对应的地标喜欢状态保持一致,因为列表页和详情页的地标数据使用的是同一份,所以可以在不同页面间保持状态同步。

star button completed

检查是否理解

问题1 下列选项哪个可以把数据按视图层级关系传递下去?

  •  @EnvironmentObject属性
  •  environmentObject(_:)修改器

问题2 绑定(binding)的作用是什么?

  •  绑定是值和改变值的方法
  •  是一个视图连接在一起的方法,确保连续起来的视图接收同一份数据
  •  是一个临时固化值的方式,目的是在其它视图状态变化时,保持值不改变

0 个评论

要回复文章请先登录注册