从 Core Data 中删除对象和切换视图控制器时崩溃

Posted

技术标签:

【中文标题】从 Core Data 中删除对象和切换视图控制器时崩溃【英文标题】:Crash when deleting object from Core Data and toggling view controllers 【发布时间】:2017-05-29 04:13:31 【问题描述】:

我正在我的初始屏幕上为一个 NSManaged 对象创建一个 NSFetchRequest。我有时会在以下情况下发生崩溃:

在我的标签栏控制器中切换到另一个视图控制器 使用相同的托管对象类型发出另一个提取请求 删除一个常见的托管对象,它也出现在我最初的 VC 的 fetchrequest 中。 VC 包含一个表格视图。 保存托管上下文 切换到第一个 VC,然后重新加载数据

我没有使用 NSFetchResutltsController 来管理这些返回的对象。当我的 tableview 重新加载时发生崩溃。我确实提出了另一个请求,并希望不会返回已删除的对象,但确实如此。当我的单元格试图读取已删除对象的属性时,它会读取uninitialized 并崩溃。在 2 个 VC 之间切换时,这种情况大约有 5 次发生。我在所有 CoreData 函数中都使用了performAndWait

有没有办法解耦两个屏幕之间托管对象的关系?如果没有,我怎样才能在第一个 VC 中获取我的 fetch 请求,而不是返回在第二个 VC 中删除的对象,使它们保持同步?

【问题讨论】:

什么是崩溃信息,它在哪一行代码崩溃? 你能在这里添加崩溃日志吗... 【参考方案1】:

NSManagedObject 与其他对象不同。它本身不包含任何信息。它有一个指向其上下文的指针和一个 objectID。当您访问它的属性时,它会将请求转发到上下文以获取所需的信息。因此,当从上下文中删除实体时, managedObject 停止工作并导致崩溃。这就是为什么通常我认为永远保留指向 managedObject 的指针并始终使用 fetchedResultsController 访问它们是一种不好的做法的原因,即使只针对一个对象,并且只有在 managedObjects 结果被丢弃后才进行获取。

您在问题中暗示了两种可能的解决方案。您可以从 managedObject 中复制值,也可以使用 fetchedResultsController。如果您复制这些值,那么即使在删除实体后它也会正常显示。如果使用 fetchedResultsController,那么 fetchedObjects 属性将永远不会包含已删除的对象,并且该对象在删除后将无法访问。

我建议使用 fetchedResultsController。你不需要害怕它。这不是很大的开销,即使您只获取一个对象,使用它也是合理的。

【讨论】:

感谢乔恩的详细回答。我将在两个屏幕之间实现 fetchResultsController。

以上是关于从 Core Data 中删除对象和切换视图控制器时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

OS X Core Data - 将托管对象上下文传递给视图控制器

Core Data 不保存对象而且速度很慢

ASP.Net Core 3.1 - 从控制器向部分视图模态传递值?

从 Core Data 中删除记录

在 Core Data 中更改托管对象模型的属性值时崩溃

如何将参数传递给 Core Data 生命周期方法?