SwiftData: 在 SwiftUI 中查询数据

346 阅读3分钟

上一篇主要介绍了如何在项目中使用 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 已经开始正常工作。效果图如下:

simulator_screenshot_3570DBC9-D9F6-4EA6-BDBE-3FFBD3B3CD6E.png

如果我们重新启动应用,会看到之前的数据仍然在那里,因为 SwiftData 自动为我们保存了数据。