外观风格
构建列表与导航
完成了基础的地标详情视图后,我们需要让用户能够查看完整地标列表,以及查看每个地标详情的方法。
在本节中,我们将会创建可显示任一地标信息的视图 ,并动态生成一个滚动列表,用户可以点按该列表以查看某个地标的详情视图。另外,我们还将通过 Xcode 的画布来显示不同设备的大小,相应的调整 UI 来适配不同的设备。

请先下载本节资源文件,并按照下面的步骤进行。
- 预计完成时间:35 分钟
- 资源文件:下载
1. 创建一个地标模型
在上一节教程中,我们把数据硬编码到了所有的自定义视图,这并不是一个好的方式。在节中,我们将通过创建的数据模型来存储数据并在视图中传递。

第 1 步
用 Xcode 打开我们在第一节内容中创建的项目,将在本节下载的资源文件里面的 Resources
目录中的 landmarkData.json
文件拖入到 Xcode 左侧的文件目录中,放置在 Landmarks 目录下;在出现的对话框中,选择 Copy items if needed
并且勾选 Landmarks
,然后点击 Finish
。
在接下来的学习中,将会使用这个样本数据。

第 2 步
带导航栏中选择 File
> New
> File
,在项目中创建一个新的 Swift File
,并命名为 Landmark.swift
。

第 3 步
Landmark.swift
文件声明了一个 Landmark
结构体,它的一些属性与 landmarkData.json
文件中的相匹配。
提示
添加 Codable
让数据在结构体和数据文件直接更容易传递。我们将在本节后面依靠 Codable 协议的 Decodable
组件来从文件中读取数据。
在接下来的几个步骤中,将会添加与每个地标相关的图像。
第 4 步
将下载的资源文件中的 Resources
目录中的 Images
下的图片拖动到项目的 Assets.xcassets
目录。Xcode 将会为每个图像创建一个新的 image set
。
也就是和上一节中的的
turtlerock
图片同一个目录。

第 5 步
给 Landmark.swift
添加一个 imageName
属性,然后再添加一个 image
图片计算属性, 用于从 Assets.xcassets
目录中加载一个图像。
提示
imageName
是一个私有属性,该属性仅用于 Landmark 结构体的内部。
第 6 步
给 Landmark
结构体中添加一个 coordinates
私有变量,该属性的类型为 Coordinates
结构体,拥有 latitude
和 longitude
两个属性。
在下一步将用它来创建一个计算属性。
第 7 步
添加 locationCoordinate
变量,这个变量将会用于与 MapKit
框架交互。
后面,我们会根据资源文件中的地标初始化一个数组。
第 8 步
在项目中创建一个新的 Swift File
,命名为 ModelData.swift
。

第 9 步
在 ModelData.swift
文件中创建一个 load(_:)
方法,用于从应用程序的主包中获取 JSON 数据
。
技巧1
load
方法的返回类型 T
是一个泛型,该泛型被限定为实现 Codable 协议
的 Decodable
类型。
技巧2
data
被声明为一个常量,在 swift 语法中,声明常量的时候可以不用即赋值;同时,一旦你将常量或者变量声明为确定的类型,你就不能使用相同的名字再次进行声明,或者改变其存储的值的类型
技巧3
load 函数
接收一个参数:filename
,而在参数前面有一个 _
符号。该符号表示函数调用的时候可以省略参数标签;也就是参数前面不加 _
符号的时候,调用 load 函数的方式为:load(filename: 'my.json')
,而加了 _
符号后,调用方式变成了:load('my.json')
;这属性 swift 语言的特性。
第 10 步
给 ModelData.swift
添加一个名为 landmarks
的变量,它的类型是 [Landmark]
,初始化值为 landmarkData.json
文件的值。
为了更好的管理文件,接下来我们先将文件进行分组管理。
第 11 步
把 ContentView.swift
、CircleImage.swift
和 MapView.swift
放到 Views
目录中,把 landmarkData.json
放到 Resources
目录中,把 Landmark.swift
和 ModelData.swift
放到 Model
目录中。
技巧4
你可以先选择要分组管理的文件,然后在Xcode 导航栏菜单中选择 File
> New
> Group from Selection
,来快速给文件创建分组。
