删除核心数据对象时如何处理外部数据的清理

我对Core Data相当陌生,遇到了别人必须遇到的问题。

我的数据模型包括图像,我保留那些外部的数据库,并简单地存储path/ URL到图像。 (根据苹果核心数据演示文稿中的build议)

当删除我的图像对象,我可以手动遍历关系,并删除图像文件,但我想知道是否有一个更优雅的方式来做到这一点。

理想的解决scheme将以某种方式与图像对象绑定,并且可以与Core Data撤消/重做一起使用。

在你的“图像”实体类中,实现willSave 。 检查[self isDeleted]并删除文件。 这推迟了文件的实际删除,直到商店被保存,这给你一些撤销能力。 设置适当的级联规则,删除图像实体,当它们的主人离开时,在那里你去。

[eta .:菲尔·卡尔文的下面的评论是正确的 – didSave可能是一个更好的地方,如果你使用多个上下文。]

[ETA。 很久以后:] MartinW提出了一个很好的观点 – 如果对象从来没有被保存过,那么保存的对象将不会被调用。 删除未保存的对象只是从上下文中取消插入,并将其丢弃,而没有特殊的生命周期事件。 只是为了使事情更复杂,你可以“撤销”和“重做”删除,包括(我认为)这种types。

想到几个方法:

这可能是重写prepareForDeletion:的情况prepareForDeletion:加上awakeFromSnapshotEvents:捕获未删除和重新删除。 为了支持撤销/重做,你不需要简单地删除当前的文件,而是使用某种“被删除”的registry(例如,当保存通知被发布时共享的可变文件名集合来清除)。 那么会/ didSave不在图片中。

或者,如果您可以使用BLOB字段而不是文件,则可以检查二进制属性中的“允许外部存储”框,将jpeg数据放在那里,并获得文件存储的一些(不是全部)优点)的头痛。 小二进制将保存在分贝; 任何大于私有阈值的内容都将被分散到一个单独的隐藏的核心数据pipe理文件中。 尽pipe如此,核心数据仍然需要将整个事件加载到NSData中。 我使用这种方法为“用户头像”型的小图片。

最后,如果image目录中没有其他内容,则可以注册didSave通知,并在保存后手动清理。 对所有Image.filename属性运行提取请求,将其与所涉及的映像目录列表进行比较,并根据需要进行删除。 我在开发过程中使用这种方法作为我的“大棒”,以确保其他一切正在做它应该做的事情。

[让我知道这些方法的成功或困难,我会保持这个最新的。]

在你的Image类中,实现-didSave 。 在这种方法中,检查[self isDeleted]是否为YES ,从磁盘上删除镜像文件。

-didSave执行此操作非常重要,尤其是如果您有多个与持久性存储关联的托pipe对象上下文。 在Core Data发现并报告 (作为保存错误)任何合并冲突之前,将发送willSave 。 这意味着你可能会收到willSave或者:

  1. 如果实施合并对象并重新尝试保存的合并策略,则需多次执行
  2. 在保存之前,由于合并冲突,永远不会向持久存储提交

过早删除图像文件可能会导致稍后从另一个托pipe对象上下文访问这些图像时发生崩溃。

我会build议覆盖图像实体prepareForDeletion方法删除磁盘上的图像文件。 该方法只会被调用,图像实体对象被实际删除。

最好的做法是(我认为这与@Rog暗示的相同)有一个存储图像的实体,并使您的对象与该实体有关系,而不是在每个对象中存储path。 在这种情况下,您只能find一个代表要删除的图片的对象,并将其删除,而反向关系可以被自动取消。