我在Core Data中有以下实体:
Project
< - >> Sheet
< - >> Attachment
(实际的班级名称已更改。每个项目都是多个工作表的父级,每个工作表都是许多附件的父级。)
这两种关系都被配置为朝向孩子(朝向多个方向)“级联”和朝向父亲(朝向一个方向)的“Nullify”。
叶实体Attachment
保存不由核心数据管理的外部图像数据:相反,它存储在文件系统中,只有文件路径存储在托管属性中。
启动时,我的应用会检查与Attachment
实体关联的图像使用的总磁盘空间,如果超过某个阈值,则会删除项目(因此表因此附件,因为:cascade)按从最旧到最新的顺序。
删除项目后,我保存了上下文,并以某种方式在awakeFromFetch()
个实例上触发Attachment
。
在awakeFromFetch()
内,附件类会检索本地保存的图像数据。路径使用父对象的(自定义)唯一标识符构建,如:
/Caches/Projects/<Project ID>/Sheets/<Sheet ID>/Attachments/<Attachment ID>/image.jpg
然而,我的应用程序在问题Attachment
时崩溃,为了构建上面的文件路径,引用了父Sheet
,而这反过来试图引用它parent Project
(刚被删除)。听起来像级联规则不起作用。另外,为什么在删除祖父母后保存孙子孙女?
崩溃时的调用堆栈看起来像这样:(某些方法名称已更改,某些中间方法被跳过)
Thread 1 Queue: com.apple.main-thread (serial)
0 specialized _assertionFailed(StaticString, String, StaticString, UInt) -> ()
1 MyStorageManager.(subdirectory in _XXXX...
2 MyStorageManager.imageForAttachment(attachment) -> UIImage?
3 Attachment.awakeFromFetch()
---------------------------
18 -[NSMangedObjectContext save:]
19 MyStorageManager.cleanup()
20 AppDelegate.init() -> AppDelegate
---------------------------
23 UIApplicationMain
24 main
25 start
好奇,我的UI(表格视图)有另一种手动删除每个Project
实例的方式,这不会触发崩溃。特别是,在这种情况下,在删除后保存上下文时不会调用Attachment.awakeFromFetch()
。
将清理代码从AppDelegate.init()
移至application(_:didFinishLaunchingWithOptions:)
并没有什么区别......