【问题标题】:Strange parent / child NSManagedObjectContext phenomenon奇怪的父/子NSManagedObjectContext现象
【发布时间】:2015-07-13 00:19:23
【问题描述】:

我创建了两个这样的上下文:

// create writer MOC
_privateWriterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateWriterContext setPersistentStoreCoordinator:_persistentStoreCoordinator];

// create main thread MOC
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.parentContext = _privateWriterContext;

我有一个用_managedObjectContext 发起的NSFetchResultedController

我知道这很奇怪,但是我正在向父级添加一条记录到_privateWriterContext,我是saving它。

令人惊讶的是子上下文和FRC 收到有关此事件的通知。为什么?我没有reset-ed 孩子,或其他任何东西。我认为只要不保存子上下文,它们就是独立的实体。


在@pteofil 文章中我发现了这一行:

当在上下文中进行更改但未保存时,它对其所有后代可见,但对其祖先不可见。

.. 它被推送到持久存储(通过持久存储协调器)并且对连接到存储的所有上下文可见。

【问题讨论】:

  • 根据这篇文章benedictcohen.co.uk/blog/archives/308,这是正常行为。
  • 还有一篇关于不同托管上下文设置性能的非常好的文章:floriankugler.com/2013/04/29/…
  • 我明白了,您认为有可能阻止更改传播到子上下文中吗?我认为在我观察到NSManagedObjectContextDidSaveNotification 并合并通知中的更改之前,更改不会传播,如果我使用两个上下文加入相同的 PSC 配置
  • 我相信这就是亲子关系的全部理念,它的设计就是这样运作的。为什么不只有 2 个单独的托管上下文,并且正如您所说,您观察 NSManagedObjectContextDidSaveNotification 以合并它们之间的更改?
  • 是的,这就是我的意思,以旧方式创建 MOC。

标签: ios core-data nsfetchedresultscontroller nsmanagedobjectcontext


【解决方案1】:

我强烈建议避免父子上下文设置。我们的书详细介绍了为什么它们经常导致奇怪的行为:https://www.objc.io/books/core-data/

简短的故事:他们并不像你想象的那么独立。

如果您需要多个上下文,请使用共享单个持久存储协调器的多个上下文。

【讨论】:

  • 我正在使用一个带有 NSMainQueueConcurrencyType 的上下文和另一个带有 NSPrivateQueueConcurrencyType 的上下文。它们各自使用自己的 NSPersistentStoreCoordinator,但指向同一个存储(NSSQLiteStoreType)。为什么我要使用单个 NSPersistentStoreCoordinator?
【解决方案2】:

这不应该发生。添加一个 NSManagedObject ('record' ) 到 parentContext,不会让孩子自动知道这个对象。只有当您让 childContext 执行 fetch 时,它才会从 parentContext 获取。 为了弄清楚你的情况是怎么回事,这里有一些建议:

  • 确定何时在 childContext 上执行提取(这是在您设置时由 fetchedRestultsController 完成的。检查该提取是在您将 managedObject 添加到 parentContext 之前还是之后发生的)。
  • 在 fetchedResultsController 的所有四个委托回调中设置断点,以找出它正在为哪个对象调用方法(并查看它是否是您刚刚添加到 parentContext 的对象)。
  • 绝对确保您也知道要发送消息的上下文。

我使用了类似的方法,但不同的是:childContext是用于解析新数据的上下文(在私有队列上),当这个解析完成时,chid调用save:。这会将更改保存到父级,在我的例子中是 mainQueueContext。这个 save: 调用将导致 mainQueueContext 接收所有新解析的对象,然后使用该 mainQueueContext 的任何 fetchedResultsController 将调用它的新/更改/更新/删除对象的委托方法。 您也可以尝试颠倒您的孩子/父母关系,看看它是否按照文档中的描述工作,只是为了了解发生了什么。

【讨论】:

    猜你喜欢
    • 2012-06-28
    • 2012-12-26
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 2016-12-24
    相关资源
    最近更新 更多