默认情况下,Core Data会添加您想要的任何对象,但这会很快变得混乱,尤其是当您知道两个或多个对象同时没有意义时。例如,如果您使用联系人的电子邮件地址存储了联系人的详细信息,则在同一电子邮件地址上附加两个或三个不同的联系人就没有意义了。
为了帮助解决这个问题,Core Data给了我们一些约束:我们可以限制一个属性,使其必须始终唯一。然后,我们可以继续根据需要创建任意数量的对象(无论是唯一的还是其他的),但是一旦我们请求Core Data保存这些对象,它将解析重复项,从而只写入一条数据。更好的是,如果已经写入了一些与我们的约束冲突的数据,我们可以选择它应如何处理合并数据。
要尝试此操作,请创建一个名为 Wizard (向导)的新实体,该实体具有一个名为“name”的字符串属性。现在选择向导实体,在数据模型检查器中查找“Constraints(约束)”,然后直接按下面的+按钮。您应该看到出现“comma,separated,properties(逗号分隔属性)”,为我们提供了一个示例。选择该示例,然后按Enter键对其进行重命名,然后改用“name”文字,这使我们的名称属性具有唯一性。记住按Cmd + S保存更改!
Constraints
现在转到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)
}
}
}
}
}
您会看到其中包含一个用于显示向导的列表,一个用于添加向导的按钮以及另一个用于保存的按钮。当您运行该应用程序时,会发现您可以多次按“Add”以将“Harry Potter”加入列表,但是当您按“Save”时,我们得到一个错误提示——The operation couldn’t be completed. (Cocoa error 133021.)
Core Data 已检测到冲突,并且拒绝保存更改。
如果要Core Data保存更改,则需要打开 SceneDelegate.swift 并添加以下代码:
import CoreData
现在,将这一行添加到willConnectTo
方法中,直接写在let context
启动的代码下方:
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
这就要求Core Data根据重复对象的属性来合并重复对象——它尝试使用新版本中的属性来智能地覆盖其数据库中的版本。如果再次运行该代码,您会看到非常棒的内容:您可以按任意多次按“Add”,但是按“Save”后,它们将全部折叠为一行,因为Core Data会删除重复项。
附:有如下合并策略可供选择:
public enum NSMergePolicyType : UInt {
case errorMergePolicyType = 0
case mergeByPropertyStoreTrumpMergePolicyType = 1
case mergeByPropertyObjectTrumpMergePolicyType = 2
case overwriteMergePolicyType = 3
case rollbackMergePolicyType = 4
}
- NSErrorMergePolicy - 冲突报错
// Default policy for all managed object contexts - save returns with an error that contain
// the object IDs of the objects that had conflicts(NSInsertedObjectsKey, NSUpdatedObjectsKey).
// 所有托管对象上下文的默认策略-保存返回的错误,该错误包含具有冲突的
// 对象(NSInsertedObjectsKey,NSUpdatedObjectsKey)的对象ID。
@available(iOS 3.0, *)
public var NSErrorMergePolicy: AnyObject
- NSMergeByPropertyStoreTrumpMergePolicy - 冲突优先使用外部更改
// This singleton policy merges conflicts between the persistent store's version of the object
// and the current in memory version. The merge occurs by individual property.
// For properties which have been changed in both the external source and in memory,
// the external changes trump the in memory ones.
// 此单例策略合并了对象的持久存储版本与当前内存版本之间的冲突。
// 按单个属性合并。对于在外部源和内存中都已更改的属性,外部更改胜过内存中的更改。
@available(iOS 3.0, *)
public var NSMergeByPropertyStoreTrumpMergePolicy: AnyObject
- NSMergeByPropertyObjectTrumpMergePolicy - 冲突优先使用数据库内版本
// This singleton policy merges conflicts between the persistent store's version of the object
// and the current in memory version. The merge occurs by individual property.
// For properties which have been changed in both the external source and in memory,
// the in memory changes trump the external ones.
// 此单例策略合并了对象的持久存储版本与当前内存版本之间的冲突。
// 按单个属性合并。对于在外部源和内存中都已更改的属性,内存中的更改胜于外部属性。
@available(iOS 3.0, *)
public var NSMergeByPropertyObjectTrumpMergePolicy: AnyObject
- NSOverwriteMergePolicy - 冲突时覆盖数据库
// This singleton policy overwrites all state for the changed objects in conflict
// The current object's state is pushed upon the persistent store.
// 此单例策略覆盖冲突中已更改对象的所有状态。当前对象的状态被推送到持久性存储中。
@available(iOS 3.0, *)
public var NSOverwriteMergePolicy: AnyObject
- NSRollbackMergePolicy - 冲突时丢弃所有更改
// This singleton policy discards all state for the changed objects in conflict.
// The persistent store's version of the object is used.
// 该单例策略丢弃冲突中已更改对象的所有状态。使用对象的持久存储版本。
@available(iOS 3.0, *)
public var NSRollbackMergePolicy: AnyObject
有条件地保存 NSManagedObjectContext | Hacking with iOS: SwiftUI Edition | 使用约束确保对象是唯一的 |
---|
赏我一个赞吧~~~
网友评论