删除*未保存的核心数据对象时如何处理外部数据的清除? [英] How to handle cleanup of external data when deleting *unsaved* Core Data objects?

查看:110
本文介绍了删除*未保存的核心数据对象时如何处理外部数据的清除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在托管对象中,我存储了应用程序容器中图像文件的路径。

当托管对象被删除时,该图像文件应该移动到垃圾桶。

In a managed object i have stored a path to an image file in the application's container.
When the managed object get’s deleted, the image file should be moved to trash. This should be done as late as possible, so that i can provide undo functionality for as long as possible.

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

I was following the answers of this question: How to handle cleanup of external data when deleting Core Data objects, and was overriding -didSave in my managed object subclass to trash the files.

结果是,只有在以下情况下才有效:

Turns out, this works only if:


  • 已添加托管对象

  • 托管对象上下文已保存 li>
  • 托管对象已删除,

  • 保存托管对象上下文。

  • the managed object has been added,
  • the managed object context has been saved,
  • the managed object has been deleted,
  • the managed object context is saved.

在下面的情况下,不会在被管对象中调用-isSaved:

In the following case however -isSaved is not called in the managed object:



  • 托管对象已删除,

  • 已保存托管对象上下文。

我明白为什么会发生这种情况。因为删除的对象从来没有持久保存,所以在删除后不会被保存,-didSave不会被调用。

I understand why this happens. As the deleted object was never persisted in the first place, it will not be saved after the deletion, -didSave is not called.

现在我正在寻找另一个地方它将引用的文件移动到垃圾桶。在哪里可以?

Now i am looking for another place from which to move the referenced file to the trash. Where could that be?

推荐答案

您有两个选择如何使用托管对象方法实现:使用托管对象生命周期事件或使用验证。
然而,这样做有一些权衡和风险有其他方法可能更好地为您工作(见建议)。

You have two choices for how to implement this using managed object methods: use the managed object life cycle events, or use validation. However, doing so has some tradeoffs and risks There are other approaches that may work better for you (see recommendations).

托管对象由拥有它们的 NSManagedObjectContext 观察。这是托管对象中的托管。实际上, NSManagedObject 实际执行的大多数操作是由 NSManagedObjectContext 执行的。托管对象是通知生命周期事件方法的变化 awakeFromFetch awakeFromInsert awakeFromSnapshotEvents: didSave didTurnIntoFault prepareForDeletion 等。当实现这些方法时,您必须小心不要以在上下文中将其标记为脏的方式更改管理对象,否则会改变当前事务。例如,尝试在 didSave 中删除​​已删除的对象,或更改 awakeFromFetch 中的关系,在 didTurnIntoFault (这将触发故障,这将是坏的)。

Managed objects are observed by the NSManagedObjectContext that owns them. This is the "managed" in managed object. Most of what a NSManagedObject instance does is actually performed by the NSManagedObjectContext. The managed object is informed of changes through the life cycle event methods: awakeFromFetch, awakeFromInsert, awakeFromSnapshotEvents:, didSave, didTurnIntoFault, prepareForDeletion, etc. When implementing these methods you must be careful to not change the managed object in a way that would mark it as "dirty" in the context or would otherwise alter the current transaction. For example, attempting to "resurrect" a deleted object in didSave, or changing relationships in awakeFromFetch, or accessing a property in didTurnIntoFault (which would fire a fault, which would be bad).

对象,生命周期事件按以下顺序调用:

During a typical deletion of a saved object, the life cycle events are called in the following order:

  • prepareForDeletion
  • validateForDelete: This is not considered a life cycle event, but it is very important. More on that in a moment.
  • willSave
  • prepareForDeletion
  • didSave
  • didTurnIntoFault

在对象的父上下文中,附加的生命周期事件可能发生在这些上下文所拥有的实例上。在处理Core Data以外的共享资源时,这一点非常重要。

If a save is subsequently done in the object's parent contexts, additional life cycle events may occur on the instances owned by those contexts. This can be very important to keep in mind when dealing with shared resources outside of Core Data.

当对象未保存并从上下文中删除时,循环事件以此顺序发生:

When an object has not been saved and is deleted from a context, the life cycle events occur in this order:

  • prepareForDeletion
  • didTurnIntoFault

在此实例中使用受管对象生命周期方法可能不是一个好的解决方案。正如你所看到的, prepareForDeletion 在你感兴趣的场景中被调用 - 但是在保存操作的情况下,删除被验证之前。

Using managed object life cycle methods may not be a good solution in this instance. As you can see, prepareForDeletion is called in the scenarios you are interested in - but it happens before the delete is validated in the case of a save operation.

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

Validation is an important Core Data capability. When objects are saved Core Data applies validation rules set in the model as well as any custom validation implemented in NSManagedObject classes. In the case of a delete, Core Data applies the delete rules defined in the model as part of the save operation. prepareForDeletion is invoked before validation occurs - so if you were trashing data as part of prepareForDeletion, you may be removing data for an object that will not actually be deleted as part of a save. This may cause you some problems.

您可以将删除作为 validateForDelete:的一部分实施,方法,检查对象的状态( isDeleted isInserted 等)。超级实现 validateForDelete:将执行删除规则,一定要正确调用它。验证将作为保存操作的一部分自动调用 ,但您可以在任何时间手动调用(建议这样做)。要手动执行验证,请从应用程序中调用适当的方法,在本例中为 validateForDelete:

You can implement your deletion as part of validateForDelete: or as a custom validation method that checks the state of the object (isDeleted, isInserted, etc.). The super implementation of validateForDelete: will execute the delete rules, be sure to call it appropriately. Validation will be called automatically as part of a save operation, but you can call it manually at any point (and this is recommended). To perform validation manually, call the appropriate method from your application, in this case validateForDelete:. Check the BOOL result, and if it returns NO, handle the error appropriately.

它可能是最好实现将图像数据写入本地文件系统作为验证或保存的一部分。当Core Data执行保存时,它实质上将作为事务的上下文中的所有更改提交。当处理外部资源时,使得对这些外部资源进行更改是很重要的。例如,在 validateImageURL:error:方法中,您应至少验证给定的URL是本地文件系统URL,并且您可以写入它。在 willSave / didSave 中,您可以写入 imageURL 如果对象已被插入或更新,并删除 imageURL 中的数据(如果已被删除)。在尚未保存但正在从上下文中删除的对象的情况下,数据将尚未提交到本地文件系统。

It may be best to implement writing the image data to the local filesystem as part of validation or saving. When Core Data performs a save, it's essentially commiting all of the changes in the context as a transaction. When dealing with external resources, it can make a lot of sense to make commiting changes to those external resources part of the same process. For example, in your validateImageURL:error: method you should at the least validate that the given URL is local filesystem URL, and that you can write to it. In willSave/didSave you may write to the URL specified by imageURL if the object has been inserted or updated, and delete the data at imageURL if it has been deleted. In the case of an object that has not yet been saved but is being deleted from the context, the data would not have yet been commited to the local filesytem. It would only exist in memory, like everything else associated with the object.

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

Note that no matter how you implement your reading, writing, and deleting of external data, you should do so using the NSFileCoordinator APIs to coordinate access to the files and directories.

此方法仍有问题。 NSManagedObjectContext (它的对象)只是对持久存储中的数据的引用的集合。如果你从一个 NSManagedObject 保存外部数据,当你有多个上下文,嵌套的上下文(你应该使用!)等等时,你可以遇到问题。NSPersistentStore是什么管理一个 NSManagedObject 的数据的持久性,并且理想情况下,您与文件系统的交互将发生在该级别 - 这将解决我提到的一些问题,更多。 这样做的最佳方式是使用Core Data的外部存储功能来管理这些数据,因为它已经内置到(一些)持久性存储中。
您还可以尝试将 NSPersistentStoreCoordinator 并覆盖 executeRequest:withContext:error:的方法来实现您自己的外部存储。

There are still issues with this approach. An NSManagedObjectContext (and it's objects) is just a collection of references to data in a persistent store. If you are saving external data from an NSManagedObject, you can run into problems when you have multiple contexts, nested contexts (which you SHOULD be using!), etc. The NSPersistentStore is what manages the persistence of an NSManagedObject's data, and ideally your interaction with the filesytem would happen at that level - which would address some of the issues that I've mentioned and more. The best way to do so would be to use Core Data's external storage capabilities to manage this data, as that is already built into (some) persistent stores. You could also attempt to subclass NSPersistentStoreCoordinator and override the method executeRequest:withContext:error: to implement your own external storage.

这篇关于删除*未保存的核心数据对象时如何处理外部数据的清除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆