Apple 似乎终于解决了 Xcode 的疯狂问题,即您在数据模型文件中所做的更改实际上并没有改变。
抛开这一点,当前的公式似乎是:
在你的核心数据单例中......
container = NSPersistentContainer(name: _nom)
// during development, right HERE likely delete the sql database file
// and start fresh, as described here stackoverflow.com/a/60040554/294884
container.loadPersistentStores { storeDescription, error in
if let error = error {
print("\n ERROR LOADING STORES! \(error) \n")
}
else {
print("\n STORES LOADED! \(storeDescription) \n")
}
self.container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.container.viewContext.automaticallyMergesChangesFromParent = true
}
您必须使用合并策略and自动合并。
然后在你的数据模型文件中
- 不要打扰,除非每段关系都有一个inverse, with
-
“对一个或多个”正确设置
- 并且(几乎可以肯定,除了非常不寻常的源数据)每个实体的唯一 ID 被指示为约束
然后当你添加新数据时,你必须
- 使用新的背景上下文受供于方便的核心数据函数可以做到这一点
- so, 永远不要尝试创建自己的单独线程
- 仔细检查您是否已完成 (1) 和 (2)!
- 当您添加一些实体时,您必须这样做inside a
perform
- 当您完成添加实体(即在新线程上)时,您必须还在表演的时候 ...
- 做一个 PerformAndWait 做两件事
- 保存新项目(在新child线程),然后
- 保存新项目(在主视图 thread)
- 当然,对于 7 和 8,您必须在保存之前检查 .hasChanges
容易吧?
所以像
let pm = core.container.newBackgroundContext()
pm.perform {
for onePerson in someNewData {
... create your new CDPerson entity ...
}
pm.bake()
}
请注意,烘焙例程位于执行块内,
它看起来像这样:
func bake() {
self.performAndWait {
if self.hasChanges {
do {
try self.save()
}
catch {
print("bake disaster type 1 \(error)")
}
}
// OPTIONALLY, SEE BELOW
if core.container.viewContext.hasChanges {
do {
try core.container.viewContext.save()
}
catch {
print("bake disaster type 2 \(error)")
}
}
// OPTIONALLY, SEE BELOW
}
}
为了清楚起见,请注意pm.bake
...在函数中bake()
, the self
上半场确实是这样newBackgroundContext
它是为执行内的循环创建的。
请注意,这些天你甚至不需要保存到主上下文
如今automaticallyMergesChangesFromParent
如果您“执行上面长列表中的所有操作”,似乎工作得很好。
• 在上面的烘焙中,添加几行打印行以查看保存到viewContext 中的内容。你会看到一切都没有被拯救。这一切都是由子/引擎中的任何关系正确完成的
• 事实上,实际上您可以省略该代码段。你所要做的就是
func bake() {
self.performAndWait {
if self.hasChanges {
do {
try self.save()
}
catch {
print("bake disaster type 1 \(error)")
}
}
}