当我学习如何使用子语境时:
let childContext =
NSManagedObjectContext(
concurrencyType: .mainQueueConcurrencyType)
childContext.parent = coreDataStack.mainContext
let childEntry =
childContext.object(with: surfJournalEntry.objectID)
as? JournalEntry
// 3
detailViewController.journalEntry = childEntry
detailViewController.context = childContext
detailViewController.delegate = self
作者对将托管对象和托管对象上下文传递给detailViewController做了一些评论:
注意:您可能想知道为什么需要将托管对象和托管对象上下文都传递给detailViewController,因为托管对象已经有了上下文变量。这是因为托管对象仅具有对上下文的弱引用。如果您没有传递上下文,ARC将从内存中删除上下文(因为没有其他内容保留它),并且应用程序将不会按预期运行。
嗯,好的,那么请阅读一些官方文档:
这意味着通常您不能依赖上下文来确保托管对象实例的寿命,并且您不能依赖托管对象的存在来确保上下文的寿命。换句话说,仅仅因为你提取了一个对象并不意味着它会留在身边。
但是,我不知道在托管对象和上下文之间进行弱引用的真正意图是什么?他们追求的目标是什么?
托管对象上下文通常使用对提取对象的弱引用来避免过度使用内存的可能性。如果它使用强引用,并且您执行了一个或多个发现大量结果的提取,则只要存在上下文,它们就会保留在内存中。在许多应用程序中,这意味着它们永远不会消失,因为在应用程序退出之前,上下文一直存在。这可能会导致应用程序为不再使用的对象使用大量内存。弱引用意味着只要应用程序停止使用它们,就会释放托管对象。
但是在某些情况下你可能想要强引用,所以有一个名为retainsRegisteredObjects
的布尔属性,它使上下文使用强引用。如果您愿意,可以使用它,但要小心使用内存。
托管对象不会保留对其上下文的强引用,以避免引用周期。如果它们是强引用并且您将retainsRegisteredObjects
设置为true
,那么您将获得一个参考周期。每个对象都会对另一个对象进行强引用,因此除非将其中一个引用设置为nil,否则它们都不能从内存中释放。
您可以将managedObject视为小而愚蠢的对象。他们有一个指向其上下文的指针并知道他们的objectId。当他们需要了解查询上下文的内容时。这有很多非常好的优点。如果实体已经在上下文中进行查询,则它的第二个实例将在上下文中命中行缓存而根本不命中存储。
通常,有两种上下文(对于大多数核心数据设置):始终在内存中的长期主队列上下文和短期背景上下文。对于主队列上下文,您通常不需要担心离开内存的上下文。它们通常在应用程序的生命周期内保留在内存中。短暂的上下文存在留下内存的问题,并且还存在它们不是线程安全的问题。所以通常它们应该在一个正确的线程上的块中创建 - 使用然后丢弃并且不会传递出块。
我希望能够解释它。