在 SwiftData
中,你可以定义模型之间的关系,并且可以执行对象关联查询。这类似于 Core Data 中的关系模型。在下面的示例中,我们将新增一个 User
模型,并创建与 TodoItem
的关联关系。
1. 定义数据模型
新增一个 User
模型,并创建与 TodoItem
的一对多关系。
import SwiftData@Model
class User {@Attribute(.primaryKey) var id: UUIDvar name: Stringvar todos: [TodoItem] = []init(id: UUID = UUID(), name: String) {self.id = idself.name = name}
}@Model
class TodoItem {@Attribute(.primaryKey) var id: UUIDvar title: Stringvar isCompleted: Bool@Relationship var user: User? // Optional relationship to Userinit(id: UUID = UUID(), title: String, isCompleted: Bool = false, user: User? = nil) {self.id = idself.title = titleself.isCompleted = isCompletedself.user = user}
}
2. 配置数据上下文
确保 User
模型也被添加到 modelContainer
中。
@main
struct MyApp: App {var body: some Scene {WindowGroup {ContentView().modelContainer(for: [User.self, TodoItem.self])}}
}
3. 使用关联查询
现在我们可以在 ContentView
中通过关联查询来获取特定用户的 TodoItem
列表。以下是如何使用 @Query
执行关联查询的示例:
import SwiftUI
import SwiftDatastruct ContentView: View {@Environment(\.modelContext) private var modelContext@State private var selectedUser: User?@State private var newItemTitle: String = ""var body: some View {NavigationView {VStack {// User selection (for demo purposes)if let users = try? modelContext.fetch(User.all()) {Picker("Select User", selection: $selectedUser) {ForEach(users, id: \.id) { user inText(user.name).tag(user as User?)}}.pickerStyle(MenuPickerStyle()).padding()}// Display todo items for the selected userif let user = selectedUser {List {ForEach(user.todos) { item inHStack {Text(item.title)Spacer()Button(action: {toggleCompletion(for: item)}) {Image(systemName: item.isCompleted ? "checkmark.circle.fill" : "circle")}.buttonStyle(PlainButtonStyle())}}.onDelete(perform: deleteItems)}HStack {TextField("New todo", text: $newItemTitle).textFieldStyle(RoundedBorderTextFieldStyle()).padding()Button(action: { addItem(for: user) }) {Image(systemName: "plus").padding()}}}}.navigationTitle("Todo List")}}private func addItem(for user: User) {let newItem = TodoItem(title: newItemTitle, user: user)modelContext.insert(newItem)newItemTitle = ""}private func toggleCompletion(for item: TodoItem) {item.isCompleted.toggle()}private func deleteItems(at offsets: IndexSet) {if let user = selectedUser {for index in offsets {let item = user.todos[index]modelContext.delete(item)}}}
}
4. 解释代码
@Relationship
: 在TodoItem
模型中,使用@Relationship
来表示与User
的关系。user
是一个可选属性,表示任务可能没有分配给任何用户。@Query
: 你可以在@Query
中使用过滤条件来获取与特定User
相关的TodoItem
,或者在这种情况下,通过user.todos
直接访问特定用户的任务列表。- 用户选择: 在示例中,我们提供了一个用户选择器(
Picker
),用于选择查看其待办事项的用户。
5. 总结
- 关系模型: 通过
@Relationship
属性,可以轻松地定义模型之间的关系,并在 SwiftData 中管理这些关系。 - 关联查询: 使用
@Query
或直接通过关系属性(如user.todos
)来执行关联查询,从而获取相关的对象数据。
这样,你可以在 SwiftUI 中有效地管理和查询关联数据。