将 NSManagedObject 的关系更改为不同的上下文

Posted

技术标签:

【中文标题】将 NSManagedObject 的关系更改为不同的上下文【英文标题】:Change relationship of NSManagedObject to different context 【发布时间】:2016-04-10 19:15:43 【问题描述】:

这是对先前问题的后续处理:Core Data: change delete rule programmatically。

我想重新表述我的问题,并会在此处进行。

简而言之,我的应用程序允许更新来自 3rd 方数据库的条目,但我想保留用户注释。所以我的工作流程是:

    遍历所有实体 下载外部 xml 并将其解析为新实体 如果是用户注释,将它们的关系从旧实体更改为新实体 删除旧实体

在导入期间,旧实体在主上下文中,新实体在临时导入上下文中。 第三个问题给我带来了问题,如果我只是改变关系,那么如果我更新我的 UI,它们就不会显示。如果我使用objectID获取注解,然后改变关系如下:

    NSManagedObjectID *objectId = oldAnnotation.objectID;
    Annotation *newAnnotation = [importContext objectWithID: objectId];
    [newEntry addAnnotationObject: newAnnotation];

它仍然不工作 - 它没有显示出来。

编辑:如果我将第二行中的上下文更改为 newEntry.managedObjectContext,我会收到 Illegal attempt to establish a relationship 'foo' between objects in different contexts 错误。

我错过了什么?

更新:经过深夜的拉扯调试,我发现我在获取newEntry时,实际上是在获取oldEntry,因此不会显示任何更改。 @Mundi 下面的答案为我指明了正确的方向。

使用我上面的代码复制旧注释,然后复制属性。对于一些本身有关系的用户输入,我必须做一个“深度复制”,我在这里找到了:How can I duplicate, or copy a Core Data Managed Object?。

【问题讨论】:

【参考方案1】:

我认为创建一个新实体并删除旧实体是一个有问题的策略。您应该尝试正确更新现有实体,并且仅在它们尚不存在时创建新实体。

每当我需要来自不同上下文的对象时,我都会获取它。话虽如此,您的对象 id 代码应该可以工作。但是,可能还有其他各种故障,您应该检查一下:

您是否保存了 importContext? 您是否保存了它的父上下文,大概是主上下文? 是否已将修改后的对象图保存到持久存储中? 您是否在保存后检查结果?

【讨论】:

我考虑过更新条目,但它们高度分支,有许多关系,每个关系都可能有一个小的更新。因此,我决定进行暴力替换,并复制用户输入的注释,而不是遍历它们,并在我正在解析的 xml 文件中找到相应的信息。除非以某种方式可以创建新条目并将其与旧条目合并,否则会覆盖任何更改。但我想这需要对所有关系进行另一次迭代,并将更改从旧条目复制到新条目。 如前所述,我相信你的蛮力方法是糟糕的设计。更新而不是创建不应引入更多复杂性或需要更多代码。为了保持一致,您还可以复制用户注释。 点好 - 我将研究更新条目。关于复制注释,您的意思是创建一个新的并复制属性吗? 是的,正在复制属性。但这只是一个建议,如果你坚持你的蛮力重建方法。 我找到了这个链接:simianzombie.com/?p=2379 - 它可能对我正在尝试做的事情有所帮助。

以上是关于将 NSManagedObject 的关系更改为不同的上下文的主要内容,如果未能解决你的问题,请参考以下文章

如何在不复制目标 NSManagedObject 的情况下将目标 NSManagedObject 添加到另一个具有反向多对多核心数据关系的对象?

NSManagedObject 子类属性

核心数据属性更改为 nil(与 ARC 相关?)

ID:[...] 的 NSManagedObject 已失效

自动生成的 NSManagedObject 中的属性

Django - 将 ForeignKey 关系更改为 OneToOne