保存子 NSManagedObjectContext 时在 NSOrderedSet 上调用额外不正确的 KVO 插入

Posted

技术标签:

【中文标题】保存子 NSManagedObjectContext 时在 NSOrderedSet 上调用额外不正确的 KVO 插入【英文标题】:Extra Incorrect KVO Insertion Called on NSOrderedSet When Saving Child NSManagedObjectContext 【发布时间】:2019-12-13 17:55:12 【问题描述】:

我有一个 NSManagedObject 和一个名为 subpointConnections_NSOrderedSet 多对多关系。我正在使用以下方法观察此集合的变化:

addObserver(self, forKeyPath: #keyPath(subpointConnections_), options: [], context: &subpointsOC)

这只能在 NSManagedObject 上的惰性属性初始化时调用一次。

任何新关系都会添加到子 NSManagedObjectContext 中,然后保存到我的主要上下文中。

当我设置关系时,我使用下面的代码,只从'one'设置关系的'many'边:

superpoint.insertIntoSubpointConnections_(self, at: index)

insertIntoSubpointConnections_ 是自动生成的访问器。

在子 NSManagedObjectContext 中,我看到一个对 observeValue(forKeyPath... 的正确调用,当调用上述插入代码时,这给了我在 subpointConnections_ 上的正确插入索引。

但是,当我保存到父 NSManagedObjectContext 时,我看到对同一对象的两次调用 observeValue(forKeyPath...。第一次调用是在NSOrderedSet 末尾插入。第二个调用是在正确的位置插入。

在每次观察调用中评估NSOrderedSet 时,新对象确实位于所描述的位置 - 它在第一次调用时位于集合的末尾,然后在第二次调用时移动到正确的位置。但是,我没有接到电话说它已从结束位置移除。

我不确定我是否在这里设置了错误。我的一对多关系中的许多对象都是唯一的,所以我可以编写代码来解决这个问题,但感觉不对。

有什么想法我可能做错了吗?

奇怪的是,传递给observeValue(forKeyPath... 的第一个更改字典包含一个NSIndexSet,第二个包含一个NSMutableIndexSet

编辑

我在一个简单的项目中复制了这个问题:https://github.com/GilesHammond/KVO-Core-Data-Extra/

在调试中运行并从应用主菜单中多次选择“添加孩子”。观察在主 NSManagedObjectContext 上显示额外错误观察的调试输出。

【问题讨论】:

即使我解决了这个问题,我也不能忽略最初的错误通知,插入然后移动操作会一直冒泡到我的界面。 【参考方案1】:

我联系了 Apple 支持并按照建议将此问题作为错误提交,因为给定的通知不是原子的。

我不得不采取不同的方法。我现在在发布 NSManagedObjectContextDidSave 通知时更新我的​​ NSManageObject。

【讨论】:

以上是关于保存子 NSManagedObjectContext 时在 NSOrderedSet 上调用额外不正确的 KVO 插入的主要内容,如果未能解决你的问题,请参考以下文章

保存子实体的重复键值

如何阻止实体框架尝试保存/插入子对象?

保存子窗口会保存父窗口(Javascript)

Netsuite 将搜索保存到 Suitelet 子列表

在 macOS 中初始化 CoreData

如何将数据保存到 mongodb 中的子文档中?我正在将农场子文档转换为 null