SwiftData:简化 iOS 数据持久化的新方法

42 min read

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 管理 PersonWish。这非常简单,只需要添加 @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 绝对值得一试。