上一篇主要介绍了如何在项目中使用 SwiftData 来定义数据模型,使我们的项目可以使用 SwiftData 的相关 API。但在移动开发中,数据都是为页面进行服务的。
而 SwiftData 与 SwiftUI 又是绝配,所以在这篇文章中我们来看下如何在 SwiftUI 的页面中来进行数据查询。
展示页面
首先,我们需要实现一个 SwiftUI 的页面,示例代码如下:
import SwiftUI
import SwiftData
struct ContentView: View {
@Query var persons: [Person]
var body: some View {
NavigationStack {
List {
ForEach(persons) { person in
VStack(alignment: .leading) {
Text(person.name)
.font(.headline)
Text(person.address)
}
}
}
.navigationTitle("SwiftDataDemo")
}
}
}
上面的代码页面部分是由 NavigationStack 实现的导航视图包裹了一个列表,列表的内容是展示 person 实例对象的名字和地址。该代码添加到 ContentView 文件中,不要忘了导入 SwiftData 框架。。。
在上一篇文章中,我们使用 modelContainer() 修饰符将 Person 注入到 SwiftUI 应用程序中,在这里我们使用 SwiftUI 代码来读取模型对象并显示它们。
上述代码中,重点在于 @Query var persons: [Person] 这一行代码。它使用 @Query 宏读取SwiftData 管理的所有 person 对象。
我们还没有创建任何数组,因此数组将为空,没关系,后面会添加创建 person 数据的方法。
@Query是非常智能的:当视图出现时,它会立即加载所有 person 数据,而且它还会会监视数据库的更改,以便无论何时添加、删除或更改任何 person 对象时,person 属性也会更新。
Tips:如果你以前使用过Core Data,这相当于 @FetchRequest 属性包装器。
因为所有的SwiftData模型对象都自动遵循 Identifiable 协议,所以我们不用再显式的为 Person 添加遵循 Identifiable 协议的代码。
添加数据
就像我之前说的,这个列表是空的,因为我们还没有创建任何数据。我们可以采取一些快捷方式并添加一些示例数据。把它放在 navigationTitle()修饰符下面:
.toolbar { Button("添加数据", action: addData) }
接着我们需要实现 addData 函数:
func addData() {
let jack = Person(name: "Jack", address: "Street-1")
let rose = Person(name: "Rose", address: "Street-2")
modelContext.insert(jack)
modelContext.insert(rose)
}
上面的代码我们可以看到使用一个对象:modelContext,我们通过调用该对象的 insert 接口去添加数据。使用它之前我们需要声明它:
@Environment(\.modelContext) **var** modelContext
模型上下文是一个重要的 SwiftData 概念,它的工作是跟踪我们的应用程序当前正在使用的所有对象。
当我们之前使用 modelContainer() 修饰符时,它也为我们创建了一个模型上下文,并将该上下文放入 SwiftUI 的环境中供我们使用。这个自动模型上下文总是运行在Swift的 MainActor 上,所以在我们的用户界面上使用它是安全的。
我们需要访问模型上下文来将我们的对象添加到 SwiftData 的存储中,如上面的代码所示,我们可以使用SwiftUI的 @Environment 属性包装器来获取它。
再次运行应用程序,然后点击《添加数据》按钮,你应该看到新的数据出现在我们的列表中。这说明 SwiftData 已经开始正常工作。效果图如下:
如果我们重新启动应用,会看到之前的数据仍然在那里,因为 SwiftData 自动为我们保存了数据。