阅读 101

[SwiftUI 100天] 条件化保存 NSManagedObjectContext

译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀

条件化保存 NSManagedObjectContext

我们之前使用NSManagedObjectContextsave()方法把所有未保存的更改 flush 到永久存储中,但我们没有实现的是检查更改是否真的需要被保存。一般来说这不会有问题,因为通常我们是在做出诸如插入或者删除的操作之后,才调用save()方法。

不过,把所有的保存动作批量处理也是很常见的,这样你可以一次保存所有的东西,对于性能的影响也更小。实际上,Apple 特别指出,我们应该总是在调用save()之前检查更改,以避免 Core Data 做不必要的工作。

幸运的是,我们可以用两种方式来检查更改。首先,每个托管对象都有一个hasChanges属性,当对象有未保存的改动时,这个属性的值为true,并且整个 context 也有一个hasChanges属性,用于检查 context 所有拥有的对象中,是否有对象包含改动。

因此,与其直接调用save(),你可以总是先做一个检查,像这样:

if self.moc.hasChanges {
    try? self.moc.save()
}复制代码

这个改动很小,但很重要 —— 做不必要的工作是没有意义的,不管这工作量有多小,尤其当你做了很多的小工程,你会意识到它们最终汇集成了大工程。


译自 www.hackingwithswift.com/books/ios-s…

通过约束确保 Core Data 对象是唯一的

默认情况下,Core Data 会添加任何你要的对象,但这样做很快会遭遇麻烦,特别是你知道两个或者更多对象相同是不合理的。举个例子,如果你用邮件地址存储了很多通讯录的细节,那么多个不同通讯录附属于相同的邮件地址就是不合理的。

为了解决这个问题,Core Data 提供了 constraints:我们可以指定某个属性被约束,以便它总是唯一的。然后我们就可以构建任意多的对象,在我们请求 Core Data 保存那些对象时,它会解决重复,确保只有一份数据被写入。更好的是,如果已经存储某些数据和约束冲突,我们可以选择如何处理数据合并。

作为尝试,我们可以创建一个新的实体,叫 Wizard,包含一个叫 “name” 的字符串属性。选择 Wizard 实体,查看数据模型监视器里的 Constraints,然后点击下面的 + 按钮。你应该会看到出现了一行 “comma,separated,properties”,这给了我们一个工作范本。选择这一行,然后点击 enter 重命名它,给它 “name” 的文本 —— 这样就要求我们的 name 属性必须是唯一的。改动之后记得点 Cmd+S 保存。

现在,回到 ContentView.swift,提供下面的代码:

struct ContentView: View {
    @Environment(\.managedObjectContext) var moc

    @FetchRequest(entity: Wizard.entity(), sortDescriptors: []) var wizards: FetchedResults<Wizard>

    var body: some View {
        VStack {
            List(wizards, id: \.self) { wizard in
                Text(wizard.name ?? "Unknown")
            }

            Button("Add") {
                let wizard = Wizard(context: self.moc)
                wizard.name = "Harry Potter"
            }

            Button("Save") {
                do {
                    try self.moc.save()
                } catch {
                    print(error.localizedDescription)
                }
            }
        }
    }
}复制代码

你会看到一张显示巫师的清单,以及一个添加巫师的按钮,一个保存的按钮。但你运行应用,你会发现你可以多次点击按钮,多个 “Harry Potter” 滑入表格,但是当你点击 “Save” 时,我们会遭遇一个错误 —— Core Data 检测到冲突,拒绝保存变动。

如果你的确希望 Core Data 写入这些变动,你需要打开 SceneDelegate.swift 添加下面这行导入:

import CoreData复制代码

然后在willConnectTo方法中添加下面这样,在let context那行后面:

context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy复制代码

这会要求 Core Data 基于对象的属性来合并重复的对象 —— 它会用新版本对象的属性智能地覆盖旧版本对象的属性。再次运行应用,现在你可以添加任意多次,不过点下保存按钮时,所有的行会坍缩成一行,因为 Core Data 剔除了所有的重复。


我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~

                                                                  


关注下面的标签,发现更多相似文章
评论