CoreData:错误:从上下文中删除托管对象后对其进行变异

Posted

技术标签:

【中文标题】CoreData:错误:从上下文中删除托管对象后对其进行变异【英文标题】:CoreData: error: Mutating a managed object after it has been removed from its context 【发布时间】:2016-07-02 11:13:23 【问题描述】:

我构建了一个简单的应用程序来检索一些 JSON 并将数据存储在 Core Data 中。

在模拟器或设备上初始安装时,所有核心数据操作都很好,但重新运行时,我收到以下错误消息:

2016-07-02 13:23:53.925 En Yakın[84775:5379467] CoreData: error: Mutating a managed object 0x79736290 <x-coredata:///Category/t4B10F995-A717-4DB8-9E87-8A1C079D45D42> (0x79736250) after it has been removed from its context.

视觉上没有任何问题。所有数据均按预期呈现,应用功能正常。

我调试了这个问题。如果我注释掉 JSON 检索函数并让应用程序在初始运行后使用 Core Data 中的内容,则不会显示任何错误消息。但是让应用再次检索会导致与我的核心数据堆栈(作为单例对象实现)的错误通信。

我应该如何修改我的核心数据实现?

更新

我相信我已经找到了问题的核心。我正在存储已下载的大约 6 KB 的缩略图。我发现存储图像会影响 Core Data 的性能。但是这种大小的缩略图也会有问题吗?如果我删除实体的图像分配,错误就会消失。我应该将它们存储在文件结构中吗?

【问题讨论】:

我猜您在处理 JSON 时断开了关系,删除规则正在删除某些内容并且您没有完全更新 UI?!? @Wain 请查看问题更新 【参考方案1】:

这个错误很有趣:

&lt;x-coredata:///Category/t4B10F995-A717-4DB8-9E87-8A1C079D45D42&gt;

注意 GUID 前面的小写 t。这意味着这个对象是新的并且没有被保存。因此,除非您在每次使用后丢弃未保存的托管对象上下文,否则这是一个完全有效的策略,您的状态不匹配。

解决问题的简单方法是发出更多 saves 或在每次新提取之前丢弃的子上下文中操作。

【讨论】:

我在玩 CoreData,我插入了一个无效的对象,然后尝试保存和回滚。保存失败,回滚从上下文中删除了这个插入的对象。之后我尝试设置此对象的属性并收到类似的错误。【参考方案2】:

如果您在 NSManagedObjectContext 上调用 reset 并尝试在调用 reset 之前使用插入到该上下文中的对象,则会发生这种情况。

let context = cdq.mainContext

let u = User.init(context: context)
u.name = "foo"

context.reset()

u.name = "bar"

这将导致CoreData: error: Mutating a managed object 0xc9891a8bcbb85cb7 &lt;x-coredata://505A879D-EC14-4A3E-8B6B-55BDD14DDC5D/Message/p260&gt; (0x7b140009ee80) after it has been removed from its context. 错误。

这不一定会使应用程序崩溃。无论哪种方式,错误都会记录到控制台。

这样做也可能导致EXC_BAD_INSTRUCTION 崩溃,如下所示:

#0  0x00007fff2516b03e in -[NSManagedObjectContext _forceRegisterLostFault:] ()
#1  0x00007fff250b81bf in _PFFaultHandlerLookupRow ()
#2  0x00007fff250c1faf in _PF_ManagedObject_WillChangeValueForKeyIndex ()
#3  0x00007fff250c39a7 in _sharedIMPL_setvfk_core ()
#4  0x00007fff250dc290 in _sharedIMPL_copying_setvfk_core ()

来自 Apple 在 NSManagedObjectContext.reset() 上的文档

所有接收者的管理对象都被“遗忘”了。如果使用此方法,则应确保同时丢弃​​对使用接收器获取的任何托管对象的引用,因为之后它们将无效。

【讨论】:

以上是关于CoreData:错误:从上下文中删除托管对象后对其进行变异的主要内容,如果未能解决你的问题,请参考以下文章

托管对象上下文不会保存——没有错误

CoreData批删除(Batch Delete)陷阱的识别与逃脱(Could not merge changes错误等)

CoreData批删除(Batch Delete)陷阱的识别与逃脱(Could not merge changes错误等)

CoreData 合并冲突显示托管对象版本更改而不是数据

使用Core Data将文本从文本字段分配到托管对象上下文

iOS CoreData+MoGenerator:如何仅在使用嵌套上下文时初始化托管对象一次?