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:崩溃,删除规则是原因吗?