gpt4 book ai didi

cocoa - 删除*未保存的*核心数据对象时如何处理外部数据的清理?

转载 作者:行者123 更新时间:2023-12-03 16:06:19 25 4
gpt4 key购买 nike

在托管对象中,我在应用程序的容器中存储了一个图像文件的路径。
当管理对象被删除时,图像文件应该被移动到垃圾箱。这应该尽可能晚地完成,以便我可以尽可能长时间地提供撤消功能。

我正在关注这个问题的答案:How to handle cleanup of external data when deleting Core Data objects , 并在我的托管对象子类中覆盖 -didSave 以删除文件。

事实证明,这只适用于:

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

  • 但是,在以下情况下,不会在托管对象中调用 -isSaved:
  • 已添加托管对象,
  • 管理对象已被删除,
  • 管理对象上下文被保存。

  • 我明白为什么会发生这种情况。由于被删除的对象从一开始就没有被持久化,删除后它不会被保存, -didSave 不会被调用。

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

    最佳答案

    对于如何使用托管对象方法实现这一点,您有两种选择:使用托管对象生命周期事件,或使用验证。
    但是,这样做有一些权衡和风险。还有其他方法可能更适合您(请参阅建议)。
    托管对象生命周期
    受管对象由 NSManagedObjectContext 观察拥有它们。这是托管对象中的“托管”。大部分是什么NSManagedObject实例确实是由 NSManagedObjectContext 执行的.管理对象为 informed of changes through the life cycle event methods :awakeFromFetch , awakeFromInsert , awakeFromSnapshotEvents: , didSave , didTurnIntoFault , prepareForDeletion等。在实现这些方法时,您必须小心,不要以在上下文中将其标记为“脏”或以其他方式改变当前事务的方式更改托管对象。例如,试图在 didSave 中“复活”一个已删除的对象。 ,或更改 awakeFromFetch 中的关系,或访问 didTurnIntoFault 中的属性(这会引发故障,这会很糟糕)。
    在保存对象的典型删除过程中,生命周期事件按以下顺序调用:

  • prepareForDeletion
  • validateForDelete:这不被认为是生命周期事件,但它非常重要。稍后会详细介绍。
  • willSave
  • prepareForDeletion
  • didSave
  • didTurnIntoFault

  • 如果随后在对象的父上下文中进行了保存,则这些上下文拥有的实例上可能会发生其他生命周期事件。在处理 Core Data 之外的共享资源时,记住这一点非常重要。
    当对象尚未保存并从上下文中删除时,生命周期事件按以下顺序发生:
  • prepareForDeletion
  • didTurnIntoFault

  • 在这种情况下,使用托管对象生命周期方法可能不是一个好的解决方案。如您所见, prepareForDeletion在您感兴趣的场景中调用 - 但它发生在保存操作的情况下验证删除之前。
    验证
    验证是一项重要的核心数据功能。当对象被保存时,Core Data 应用模型中设置的验证规则以及 NSManagedObject 类中实现的任何自定义验证。在删除的情况下,Core Data 应用模型中定义的删除规则作为保存操作的一部分。 prepareForDeletion在验证发生之前调用 - 因此,如果您将数据作为 prepareForDeletion 的一部分进行了垃圾处理,您可能正在删除在保存过程中实际上不会被删除的对象的数据。这可能会给您带来一些问题。
    您可以将删除作为 validateForDelete: 的一部分实现或作为检查对象状态的自定义验证方法( isDeletedisInserted 等)。 validateForDelete:的 super 实现将执行删除规则,一定要适本地调用它。验证将作为保存操作的一部分自动调用,但您可以随时手动调用它(建议这样做)。要手动执行验证,请从您的应用程序调用适当的方法,在本例中为 validateForDelete: .检查 BOOL 结果,如果返回 NO,则适当处理错误。
    建议
    作为验证或保存的一部分,最好实现将图像数据写入本地文件系统。当 Core Data 执行保存时,它本质上是将上下文中的所有更改作为事务提交。在处理外部资源时,在同一流程中提交对这些外部资源的更改是很有意义的。例如,在您的 validateImageURL:error:您至少应该验证给定的 URL 是本地文件系统 URL,并且您可以写入它。在 willSave/ didSave您可以写入 imageURL 指定的 URL如果对象已插入或更新,则删除 imageURL 处的数据如果已经被删除。如果对象尚未保存但正在从上下文中删除,则数据尚未提交到本地文件系统。它只会存在于内存中,就像与对象相关的所有其他东西一样。
    请注意,无论您如何实现对外部数据的读取、写入和删除,都应该使用 NSFileCoordinator APIs 来实现。协调对文件和目录的访问。
    这种方法仍然存在问题。安 NSManagedObjectContext (及其对象)只是对持久存储中数据的引用的集合。如果您从 NSManagedObject 保存外部数据,当你有多个上下文、嵌套上下文(你应该使用!)等时,你可能会遇到问题。 NSPersistentStore 是管理 NSManagedObject 的持久性的东西。的数据,理想情况下您与文件系统的交互将发生在该级别 - 这将解决我提到的一些问题以及更多问题。 最好的方法是使用 Core Data 的外部存储功能来管理这些数据,因为它已经内置到(某些)持久存储中。
    您也可以尝试子类化 NSPersistentStoreCoordinator并覆盖方法 executeRequest:withContext:error:实现您自己的外部存储。

    关于cocoa - 删除*未保存的*核心数据对象时如何处理外部数据的清理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25603227/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com