当上下文初始化为内联时,为什么 NSManagedObject 不会插入到子 NSManagedObjectContext 中?

And*_*net 2 core-data nsmanagedobject nsmanagedobjectcontext ios swift

NSManagedObjectContext在我的 iOS 应用程序中使用 child 作为便签本。我正在使用 的扩展NSManagedObjectContext来创建子上下文,如下所示:

extension NSManagedObjectContext {
    func childContext(concurrencyType: NSManagedObjectContextConcurrencyType = .mainQueueConcurrencyType) -> NSManagedObjectContext {
        let childContext = NSManagedObjectContext(concurrencyType: concurrencyType)
        childContext.parent = self
        return childContext
    }
}
Run Code Online (Sandbox Code Playgroud)

NSManagedObject当将新的内容插入新的子上下文(从viewContexta创建NSPersistentContainer)时,我的应用程序的一部分重复出现错误,并显示以下消息:

CoreData:错误:从上下文中删除托管对象后对其进行更改

这很奇怪,因为应用程序的其他部分(也使用子上下文)运行良好。NSManagedObject最终,我将原因缩小到将新的(实体名称“Book”)插入新的子上下文的方式上的一个小差异。以下内容按预期工作:

let childContext = container.viewContext.childContext()
let object1 = NSEntityDescription.insertNewObject(forEntityName: "Book", into: childContext)
print(object1.managedObjectContext == nil)
// prints "false"
Run Code Online (Sandbox Code Playgroud)

但是,如果我内联创建子上下文(即未分配给变量,则托管对象不会插入到上下文中):

let object2 = NSEntityDescription.insertNewObject(forEntityName: "Book", into: container.viewContext.childContext())
print(object2.managedObjectContext == nil)
// prints "true"
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很奇怪并且无法弄清楚。一切都在主线程上运行。我还创建了一个Swift 游乐场来重现这种行为。

Tom*_*ton 5

托管对象有一个managedObjectContext属性,但它是一个弱引用。这意味着拥有托管对象并不能阻止上下文被释放。如果上下文被释放,该managedObjectContext属性将自动设置为 nil。

在您的第一个代码片段中,childContext它作为创建托管对象的代码中的局部变量存在。插入新对象后,它仍然存在于本地范围内,因此该managedObjectContext属性仍然指向上下文。该childContext变量保持强引用,因此该对象仍然存在。

在第二个片段中,子上下文仅作为 的参数存在insertNewObject。一旦该方法返回,上下文就会超出范围。由于没有对上下文的强引用,它会被释放,并object2.managedObjectContext自动设置为 nil。