deleteObject: 如何在 coreData 中工作?

Posted

技术标签:

【中文标题】deleteObject: 如何在 coreData 中工作?【英文标题】:How does deleteObject: work in coreData? 【发布时间】:2011-06-22 04:07:52 【问题描述】:

我只是冒险并在 CoreData 之上重写了我的应用程序(以前我使用自己的内部保存格式)。

虽然我对 deleteObject: 的行为有点困惑,但事情大部分都在工作。

我有一个对象,它是我的图表的一部分,当我删除它时,该对象似乎没有发生任何事情。该对象具有一些关系,其中一些是“级联”,一些是“无效”。与对象的每个关系都具有反向关系。

删除对象后,唯一似乎发生变化的是在我的对象上设置了“isDeleted”标志。所有的关系都像以前一样存在。

如果我尝试使用 NSFetchRequest 查找对象,它不会找到已删除的对象。但是,如果我使用 KVC 关系遍历我的图,则返回的 NSSet 包含所有对象,包括已删除的对象。

在我将 save: 方法发送到我的 ManagedObjectContext 之后,一切都如我所料。

当我进行删除时,我是否需要手动清除我不想要的关系,或者我需要持续保存以保持我的数据健全?这对我来说似乎非常违反直觉。

我可以做些什么来“提交”删除,或者至少让我的对象图在没有保存的情况下保持理智。每次我想修改我的图表时都进行保存似乎有点激烈。

谢谢, 罗恩

附言以下是一些我觉得很奇怪的行为:

在删除对象之前,这是对具有 categoryObjs “对多”关系的父对象的“描述”:

categoryObjs =     (
    "0x613e1a0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p9>",
    "0x613e1b0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p12>",
    "0x613e190 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p7>"
);

删除“p12”对象(上图中间那个)后,通过KVC访问时,关系的状态并没有改变。如果我尝试获取 TestCategory 实体,则只找到两个。

“保存:”后 p12 对象消失:

categoryObjs =     (
    "0x613e1a0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p9>",
    "0x613e190 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p7>"
);

【问题讨论】:

【参考方案1】:

每次调用save:,您的托管对象上下文都必须返回存储并实际写入更改。这是昂贵的。因此,deleteObject: 只是将对象标记为已删除,下次保存时实际上会应用该对象。 (请记住,这也有助于撤消功能,它只是与您想要做的事情背道而驰。)

根据文档,isDeleted 属性仅说明对象是否将在下一次提交时被删除,并在对象上设置isDeleted 标志。此外,如果从未提交过,deleteObject: 将从上下文中删除接收者。

例如(其中对象 A 和 B 是 NSManagedObject 实例):

    创建对象 A 保存 MOC 删除对象 A

对象 A 已被标记为删除,但在您再次执行第 2 步之前并未真正删除。

对比一下:

    创建对象 B 删除对象 B

对象 B 消失了,因为它从未保存过,所以没有“标记删除”。它已经消失了。

编辑:

我只是好奇,您是否将 NSFetchedResultsController 用于您的 tableview 的数据源?值得一看,如果您还没有的话。

【讨论】:

感谢您的回复!但是,我仍然很困惑。如果我删除一个对象,我希望它不会出现在我的应用程序中。例如,我有一个对象表。用户从表中删除一个对象,然后我向我的上下文发送“deleteObject:”消息以删除该对象。我希望该对象不会出现在表格中。我可以手动检查 isDeleted 属性,但这非常繁琐并且极易出错。更糟糕的是,这种行为似乎不一致。有时对象会消失,有时对象不会。 听起来你误解了deleteObject方法的概念。它实际上并没有删除对象。如果您想确认删除,那么请继续并调用保存。另外,我很好奇,您是否将 NSFetchedResultsController 用于您的 tableview 的数据源?值得一看。 感谢您的回复。我现在没有使用 NSFetchedResultsController - 我可以查看它,尽管我在很多地方迭代对象。那么真的没有办法在不进行保存的情况下实际删除对象吗:?我转换为 CoreData 的原因之一是让它为我自动化了很多这种行为。无论如何我需要手动完成吗?我不在乎对象是否真的从磁盘或内存中删除,但我确实想要一种能够更新内存中的对象图的方法,包括插入(立即发生)和删除(不会发生)。 查看 NSFetchResultsController,它设计用于处理表视图。我认为这将极大地增强您使用 Core Data 的体验。此外,Apple 的开发者网站上有一段很棒的视频(需要登录)。让我看看能不能找到链接。 感谢摩西!感谢您的建议。转换为使用 CoreData 带来了一些很大的好处,但也有点让人头疼。如果没有真正的“有序列表”支持,很难将对象图用于您的核心数据结构,并且无法删除内存中的对象对我来说有点震惊。我确信它为什么会这样工作是有合理的理由的,尽管我不确定它是什么。 Apple 关于 Core Data 的文档确实建议在每次用户与数据库交互后进行保存,这就是我现在正在做的事情。【参考方案2】:

我认为 Core Data 希望在 deleteObject: 时尽量减少内存和 IO 使用,并在 save: 中完成所有繁重的工作,例如写入 sqllite 文件。这可能是最省时的方式。

【讨论】:

感谢您的回复!但是,我仍然很困惑。我做了更多的实验,我上面报告的行为有时会发生,而不是其他的。我并不真正关心幕后发生的事情,但是当我删除一个对象时,它至少需要在我的应用程序中显示为已删除(即我希望删除的对象不会出现在任何地方,除非我仔细查看例如查看 NSManagedObjectContext 返回的 deletedObjects 列表。

以上是关于deleteObject: 如何在 coreData 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

DeleteObject 方法不来

deleteObject 在 Realm 中不起作用

核心数据:-deleteObject:崩溃,删除规则是原因吗?

如何轻松删除领域中的所有对象

UITableView中的deleteObject错误,无法复制

为啥 deleteObject: 导致 CoreData 故障?