
1.5 为卡片创建数据模型
本节我们将创建数据模型对象,有了这样的模型,就可以将真正的数据信息呈现到卡片上供用户浏览了。
1.5.1 创建卡片数据模型
在项目导航中添加一个新的Swift类型的文件,如图1-24所示,将文件命名为CardModel。

图1-24 在文件模板对话框中选择Swift类型文件
文件创建好以后就可以为卡片的所有关键信息创建数据模型了,代码如下。

这里使用结构体(Struct)定义卡片的数据模型,在该结构体中会用到SwiftUI框架中的Color结构体,所以一定要将之前的Foundation框架替换为SwiftUI框架。
需要注意的是,因为该结构体要符合Identifiable协议,也就是通过该结构体被实例化的每个对象都必须是唯一的、可标识的,所以必须在结构体中包含一个id属性,并且id属性的值也必须是唯一的、可标识的。因此这里使用UUID()函数的值作为id的值,UUID()函数会随机生成一个唯一的值。
然后,我们在结构体中定义卡片的标题、内容提要、图片文件名、按钮标题、相关信息、背景渐变色。gradientColors是Color类型的数组,之前在Assets.xcassets中我们一共添加了14种不同的颜色集,这里就利用它们生成线性渐变色背景。
在CardModel结构创建完成以后,我们还需要添加一个新的文件存储真正的人物资料数据。
1.5.2 为静态数据创建数组
接下来,我们需要创建供CardModel使用的数据信息。因为这一章是本书的起始章节,所以我们会使用最简单、最容易实现的方式来组织这些数据。之后,随着学习的不断深入,我们会使用更为专业的方法。
我们需要在新的Swift文件中创建数组。所以先在项目导航中创建一个新的Swift类型文件,将其命名为CardData。需将文件中的代码修改为下面这样。

现在,我们已经为cardData数组添加了一个Card类型的元素对象,如果你愿意,那么还可以继续添加其余的6个元素,或者直接复制已经提供好的数据。在“项目资源/Data”中,将CardData.txt文件中的所有数据复制到let cardData:[Card]=[]数组中即可。
1.5.3 在卡片中显示数据信息
本节的主要任务是将数据呈现在卡片上,在对CardView的代码进行调整之前,先注释掉ContentView中ForEach里面对CardView()的调用。

之所以这样做,是因为接下来我们会在CardView中添加属性,新添加的属性会改变CardView的调用方式,如果沿用之前的方式,编译器就会报错,影响我们的测试。
接下来,在项目导航中选择CardView.swift文件,为该结构体添加一个属性,代码如下。

你可能会注意到,此时在Xcode的顶部会出现一个红圈叉报错,编译器此时会停止工作。导致错误的原因是在Preview部分,我们没有在实例化CardView()的时候为card变量赋值。
要想快速修复这个错误,可以单击错误行右侧的红色圆点,然后在错误描述面板中单击Fix即可,如图1-25所示。

图1-25 快速修复未初始化属性的错误
此时,我们需要为CardView()提供一个Card类型的对象参数。之前在CardData中已经创建好了cardData数组,因此,这里只需要提供给它数组中的一个元素即可。将报错行修改为CardView(card:cardData[1]),Xcode顶端的红圈叉消失,编译器又开始正常工作了。
接下来就要修改Body部分的代码了,因为之前我们都是手动将信息强行写入代码中的,所以现在需要将这部分代码全部修改为card变量的形式,修改代码如下。


这里我们一共修改了6处,调用的是Card对象的5个属性:title、headline、imageName、callToAction和gradientColors。为了验证是否成功,可以修改Preview部分cardData数组的索引值,看看是否更新了不同的人物信息,如图1-26所示。

图1-26 7张不同的人物卡片效果
这时,让我们回到ContentView,如同CardView一样,在Properties部分添加一个新的属性。


因为cards数组中的元素均符合Identifiable协议,所以在ForEach循环中可以直接通过cards遍历数组中的每个元素信息。此时的item代表的就是cards数组中的元素,因此可以将其作为参数传递给CardView。
构建并在模拟器中运行该项目,效果如图1-27所示。

图1-27 在模拟器中运行的效果