SwiftData:简化 iOS 数据持久化的新方法
在 WWDC 2023 上,Apple 推出了一个新的数据持久化框架:SwiftData。SwiftData 使用了更符合 Swift 语言风格的声明式语法,让开发者能更简单地定义模型、访问和查询数据以及处理数据的插入和删除。不仅如此,SwiftData 甚至不需要额外的依赖,它提供了一种更直观、更“Swifty”的方式来处理 iOS 中的持久性数据存储。本文将以一个多人愿望列表的实例,介绍如何使用 SwiftData。
环境要求
要使用 SwiftData,你需要使用 iOS 17 和 Xcode 15 Beta 1 或更高版本。
定义模型
首先,我们定义一个 Person
类来描述一个人,以及一个 Wish
类来描述每个人的愿望。同时,我们也让每个人都有一些朋友。
class Person { let id: UUID var name: String var friends: [Person] = [] var wishList: [Wish] = [] init(name: String, friends: [Person], wishList: [Wish]) { self.id = UUID() self.name = name self.friends = friends self.wishList = wishList } } class Wish { var content: String var owner: Person init(content: String, owner: Person) { self.content = content self.owner = owner } }
现在我们需要让 SwiftData 管理 Person
和 Wish
。这非常简单,只需要添加 @Model
即可。
@Model class Person { // ... } @Model class Wish { // ... }
配置模型属性
在我们的 Person
类中,每个人的身份证号码应该是唯一的。为了实现这个需求,我们可以添加 @Attribute(.unique)
。
@Attribute(.unique) let id: UUID
此外,当我们删除一个人时,他的愿望也应该被删除。为此,我们可以使用 @Relationship(.cascade)
。
@Relationship(.cascade) var wishList: [Wish] = []
如果有某个属性你不希望被 SwiftData 持久化,你可以使用 @Transient
标记该属性。
创建 ModelContainer
ModelContainer 根据 Schema 的描述来生成一个对应的数据库实例,并且也会负责 Schema 的更新、迁移等。
如果你不使用 SwiftUI,你可以创建一个 ModelContainer。
let container = try ModelContainer([Person.self, Wish.self])
如果你使用 SwiftUI,那么可以使用更简单的方式创建 ModelContainer。
@main struct SwiftDataDemoApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: [Person.self, Wish.self]) } }
使用 ModelContext 进行操作
你需要使用 ModelContext 来进行数据的监听更新、获取、保存修改和撤销修改。
在 SwiftUI 中,你可以在任何一个视图中使用 @Environment
获取上下文(context)。
struct ContentView: View { @Environment(\.modelContext) private var context}
如果你不使用 SwiftUI,那你可以通过 ModelContainer 来获取 ModelContext。
let context = container.mainContext
或者通过 ModelContext 的初始化方法传入 ModelContainer 的方式获得 context。
let context = ModelContext(container)
在获取了 ModelContext 后,你就可以进行数据的添加、删除、修改和查询操作了。
对不起,我忽略了这一点。让我们添加关于如何使用 ModelContext 进行数据操作的具体说明:
插入数据
你可以使用 insert
方法向数据库中插入新的数据。以下是一个例子:
let person = Person(name: "张三", friends: [], wishList: []) context.insert(person)
删除数据
你可以使用 delete
方法从数据库中删除数据。以下是一个例子:
context.delete(person)
修改数据
你可以直接修改模型的属性,然后调用 save
方法将更改保存到数据库。以下是一个例子:
person.name = "李四" try context.save()
注意,save
方法可能会抛出错误,所以你需要使用 try
关键字。
查询数据
你可以使用 fetch
方法获取数据库中的数据。以下是一个例子:
let descriptor = FetchDescriptor<Person>(sortBy: [SortDescriptor<Person>(\.name)]) let persons = try context.fetch(descriptor)
在这个例子中,我们首先创建了一个 FetchDescriptor
,用于描述我们的查询条件。然后,我们使用 fetch
方法执行查询。
如果你使用 SwiftUI,你可以使用 @Query
属性包装器进行查询。以下是一个例子:
@Query(sort: \.name, order: .forward) private var persons: [Person]
在这个例子中,我们使用 @Query
属性包装器查询数据库中所有的 Person
,并按照 name
进行排序。
以上就是如何使用 SwiftData 的 ModelContext 进行数据的插入、删除、修改和查询操作。希望这些信息能对你有所帮助!
iCloud 的支持
SwiftData 提供了对 iCloud 的支持,可以让你的数据在用户的多个设备之间进行同步。为了实现这个功能,你需要设置 ModelContainer 的配置,并打开 CloudKit 功能。
首先,确保你的应用已经开启了 iCloud 和 CloudKit 功能。你可以在 Xcode 的 Target 设置中的 "Signing & Capabilities" 选项卡里添加 iCloud Capability,并在 iCloud Capability 的选项中打开 CloudKit。
接下来,你需要创建一个 ModelConfiguration 对象,并设置 iCloudContainerIdentifier。iCloudContainerIdentifier 应该与你在 iCloud Capability 设置中指定的 Container Identifier 相符。
以下是一个例子:
let schema = Schema([Person.self, Wish.self]) let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "iCloud.com.yourcompany.yourapp")! let configuration = ModelConfiguration(iCloudContainerIdentifier: "iCloud.com.yourcompany.yourapp", url: containerURL) let container = try ModelContainer(for: schema, configuration: configuration)
在这个例子中,我们首先创建了一个 Schema 对象。然后,我们使用 FileManager 的 containerURL(forSecurityApplicationGroupIdentifier:) 方法获取了我们应用的 iCloud Container 的 URL。接着,我们创建了一个 ModelConfiguration 对象,并设置了 iCloudContainerIdentifier 和 url。最后,我们使用 Schema 和 ModelConfiguration 创建了一个 ModelContainer。
现在,你的数据应该可以在用户的多个设备之间进行同步了。当你在一个设备上插入、删除或修改数据时,这些更改将自动同步到其他设备上。
请注意,你需要确保每个设备都登录了相同的 iCloud 账户,并打开了 iCloud Drive 功能。
总结
SwiftData 提供了一种更直观、更符合 Swift 风格的方式来处理数据的持久化。它大大简化了 Core Data 的使用,使得开发者可以更容易地定义模型和操作数据。如果你正在寻找一种新的、简单的方式来处理 iOS 中的数据持久化,那么 SwiftData 绝对值得一试。