【问题标题】:ViewContext not receiving updates from newBackgroundContext()ViewContext 未从 newBackgroundContext() 接收更新
【发布时间】:2019-11-12 03:47:56
【问题描述】:

堆栈溢出中已经有类似的问题,但它对我不起作用。

在我的应用程序中有一个用例,我必须观察数据库更改才能执行某些操作。为了接收更新,我订阅了NSManagedObjectContextObjectsDidChange 通知(用于 ViewContext),并且我打开了automaticallyMergesChangesFromParent

但是,如果我在其他上下文中 updatedelete 对象(使用 newBackgroundContext()),我不会收到对象确实更改通知,但它对于 inserting 新对象非常有效。

有人可以指导我为什么即使启用automaticallyMergesChangesFromParent 后它也只适用于插入,而不适用于更新和删除?如果这是实际行为,还有其他方法可以解决我的用例吗?

.automaticallyMergesChangesFromParent 的文档(NSManagedObjectContext.h)说:

上下文是否自动合并保存到它的更改 协调者或父上下文。将此属性设置为 YES 时 不支持将上下文固定到非当前查询生成。

我尝试了什么

  • 我通过测试是否已经更新/删除的对象进行了调试 在视图上下文中注册。是的,这些都已经注册了。
  • 我用NSFetchResultController测试了同样的东西,它工作正常 很好,但不幸的是,我不能像我一样使用NSFetchResultController 使用自定义视图来表示数据
  • 另外,我尝试创建一个新的privateQueueConcurrencyType 上下文并将viewContext 设置为父级,它令人惊讶地开始工作,所以问题仅在使用newBackgroundContext() 时出现,但根据文档,它应该可以正常工作,因为两者都使用相同NSPersistentStoreCoordinator

提前致谢!

【问题讨论】:

  • 您为什么使用通知?你可以使用 fetchedResultsController 来监控上下文吗?
  • 在我的用例中,我不能使用 FRC,所以我决定使用通知,请参阅下面的链接。 stackoverflow.com/questions/55686097/…
  • 顺便说一句,如果您认为它会在 FRC 中运行良好,那么为什么它不在通知中我真的相信 FRC 也会在幕后观察相同的通知。
  • 1) 怀疑问题是对象在您将更改合并到的上下文中没有错误(我不确定,所以我不做这个答案)。 2)我读了你的另一个问题。您仍应使用 FRC。我总是使用 FRCS。我什至只对一个对象使用 FRC。 (也许使用2?)。祝你好运!
  • 我尝试在示例项目中使用 FRC,它运行良好,但在我的用例中,我将在 3 个不同的 UI 中显示数据,其中只有一个是表格视图,我可以在其中使用 FRC 它可以解决剩下的两个呢?我在哪里使用 fetch request 获取数据并在自定义视图中显示它们在这里我们不需要使用 FRC 我们如何解决它?

标签: ios core-data nsmanagedobject nsmanagedobjectcontext nspersistentcontainer


【解决方案1】:

“我不能使用NSFetchResultController,因为我使用自定义视图来表示数据”不正确,FRC 可以而且应该用于任何视图(显示多个对象)。

至于为什么在更新(更新后出现)或删除的情况下您没有收到NSManagedObjectContextObjectsDidChange,我有一些理论:

  1. 可能不正确地称为_persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES;,因为这正是您描述的情况(接收插入但不接收更新或删除)。它应该在 loadPersistentStoresWithCompletionHandler 之后的应用委托中的 persistentContainer 自定义 getter 中完成(而不是在块内)。

  2. 可能没有在您的背景上下文中使用performBlock

  3. 可能未正确注册更改通知。

  4. (根据新信息)不保留获取的对象。

如果您想分享一些代码,我们可以帮助您追踪错误。

【讨论】:

  • 感谢您的回复。我检查了我的代码,您提到的所有三个都已完美实现,因此不会有问题。我在更新托管对象之前进行了调试,无论它是否已经注册到视图上下文中,但结果是 NO,这意味着视图上下文在某处丢失了它的对象。我正在使用视图上下文获取对象并将它们转换为自定义对象以在 UI 中使用它。此处获取的托管对象范围仅限于特定的获取方法。你认为这会是一个问题吗?如果获取的对象被释放,上下文会丢失注册的对象吗?
  • 是的,这就是问题所在。您需要保留获取的对象,例如在强大的数组属性中。您可以在 NSManagedObject 子类上创建自定义属性,以将来自对象的数据格式化为您希望在 UI 中使用的内容。您还可以使用 KVO 注册依赖键在构成 UI 显示属性的值发生更改时收到通知。
【解决方案2】:

可能不完全是一个答案,而只是一些想法和建议,结构不够好,无法发表评论。

这可能与 viewContext 没有保留对象有关,而只是由于不再直接使用它们(例如在 tableview 中)而导致的错误。为此会有 retainsRegisteredObjects

另外,您是否访问过 viewContext 中已更改的属性?这也可能是一个问题,它无法识别从未被读取的对象上的更改。

我强烈建议在这些情况下使用一个或多个 FRC,它们会为您桥接通知并提供更简洁的界面。如果您有自定义视图并不重要,只需实现 FRCDelegate 方法就可以了。我认为,如果您问另一个问题,为什么您不能在自定义视图中使用 FRC(问题出在哪里?),这可能会更容易为您提供帮助。

【讨论】:

  • 感谢您的回复! 1)我尝试启用 retainsRegisteredObjects 它通知第一个更新,但它未能通知连续更新 2)不,我没有访问在视图上下文中已更改的属性 3)是的,我在某些地方阅读它就像使用 FRC如果我们不以任何方式使用表格视图/集合视图,则不建议使用我通过创建新的私有队列并发类型上下文并将视图上下文设置为父级来解决它,但我真的很想知道为什么它在我的第一个中不起作用按照文档的方法应该可以很好地工作
  • 也许您可以尝试按照 2.) 中的描述首先访问应该更改的属性?也许这有助于@thavasidurai
猜你喜欢
  • 2017-01-13
  • 2021-03-23
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 2017-10-03
  • 2022-06-10
  • 2015-05-07
相关资源
最近更新 更多