删除*unsaved*Core Data对象时如何处理外部数据的清理?

Mar*_*inW 7 cocoa core-data nsmanagedobject nsmanagedobjectcontext

在托管对象中,我已经存储了应用程序容器中图像文件的路径.
删除托管对象后,应将图像文件移至废纸篓.这应该尽可能晚地完成,以便我可以尽可能长时间地提供撤消功能.

我正在按照这个问题的答案:如何在删除Core Data对象时处理外部数据的清理,并在我的托管对象子类中重写-didSave以废弃文件.

事实证明,这仅适用于:

  • 已添加托管对象,
  • 托管对象上下文已保存,
  • 托管对象已被删除,
  • 托管对象上下文已保存.

但是,在以下情况中,未在托管对象中调用-isSaved:

  • 已添加托管对象,
  • 托管对象已被删除,
  • 托管对象上下文已保存.

我理解为什么会这样.由于删除的对象从未在第一个地方持久存在,因此在删除后不会保存它,也不会调用-didSave.

现在我正在寻找另一个将引用文件移动到垃圾箱的地方.那可能在哪里?

que*_*ish 9

对于如何使用托管对象方法实现此操作,您有两种选择:使用托管对象生命周期事件,或使用验证.但是,这样做有一些权衡和风险还有其他方法可能对您更有效(见建议).

管理对象生命周期

管理对象由NSManagedObjectContext拥有它们的人观察.这是托管对象中的"托管".NSManagedObject实例所做的大多数实际上是由NSManagedObjectContext.管理对象是通过生命周期事件方法的改变获悉:awakeFromFetch,awakeFromInsert,awakeFromSnapshotEvents:,didSave,didTurnIntoFault,prepareForDeletion,等.当实现这些方法,你必须小心的将其标记为"脏"的背景下的方式不改变管理对象或以其他方式改变当前的交易.例如,尝试"复活"已删除的对象didSave,或更改关系awakeFromFetch,或访问属性didTurnIntoFault(这将触发故障,这将是坏事).

在典型删除已保存对象期间,将按以下顺序调用生命周期事件:

如果随后在对象的父上下文中完成了保存,则在这些上下文拥有的实例上可能会发生其他生命周期事件.在处理Core Data之外的共享资源时,请记住这一点非常重要.

如果某个对象尚未保存并从上下文中删除,则生命周期事件将按以下顺序发生:

在这种情况下,使用托管对象生命周期方法可能不是一个好的解决方案.正如您所看到的,prepareForDeletion在您感兴趣的场景中调用 - 但它是在保存操作的情况下验证删除之前发生的.

验证

验证是一项重要的核心数据功能.保存对象时,Core Data会应用模型中设置的验证规则以及NSManagedObject类中实现的任何自定义验证.在删除的情况下,Core Data应用模型中定义的删除规则作为保存操作的一部分.验证发生之前prepareForDeletion调用- 因此,如果您将数据作为一部分删除,则可能会删除实际上不会作为保存的一部分删除的对象的数据.这可能会导致一些问题.prepareForDeletion

你可以实现你删除的部分validateForDelete:是检查对象的状态定义验证方法或为(isDeleted,isInserted,等).超级实现validateForDelete:将执行删除规则,请务必适当调用它.验证将作为保存操作的一部分自动调用,但您可以随时手动调用(建议这样做).要手动执行验证,请在您的应用程序中调用相应的方法,在本例中validateForDelete:.检查BOOL结果,如果返回NO,则适当处理错误.

建议

作为验证或保存的一部分,最好将图像数据写入本地文件系统.当Core Data执行保存时,它实际上将上下文中的所有更改作为事务提交.在处理外部资源时,对同一进程中的外部资源进行提交更改是很有意义的.例如,在您的validateImageURL:error:方法中,您至少应该验证给定的URL是本地文件系统URL,并且您可以写入它.在willSave/ didSave您可以写入指定的URL,imageURL如果已插入或更新对象,并删除数据,imageURL如果已删除.对于尚未保存但正从上下文中删除的对象,数据尚未提交到本地文件系统.它只会存在于内存中,就像与该对象相关的所有其他内容一样.

请注意,无论您如何实现外部数据的读取,写入和删除,都应该使用NSFileCoordinator API来协调对文件和目录的访问.

这种方法仍然存在问题.一个NSManagedObjectContext(和它的对象)仅仅是在持久存储数据的引用的集合.如果要从中保存外部数据NSManagedObject,当有多个上下文,嵌套上下文(您应该使用它们等等)时,可能会遇到问题.NSPersistentStore管理数据的持久性NSManagedObject,理想情况下是您的交互filesytem会发生在那个级别 - 这将解决我提到的一些问题以及更多.最好的方法是使用Core Data的外部存储功能来管理这些数据,因为它已经内置到(某些)持久性存储中. 您还可以尝试子类化NSPersistentStoreCoordinator并覆盖该方法executeRequest:withContext:error:以实现您自己的外部存储.