为什么删除时会引发 Core Data NSManagedObject 错误?

And*_*net 5 core-data nsmanagedobject nsmanagedobjectcontext ios swift

我正在尝试有效地批量删除大量NSManagedObjects (不使用NSBatchDeleteRequest)。我一直遵循这个答案中的一般过程(适用于 Swift),通过批处理请求对象、删除、保存然后重置上下文的操作。我的获取请求设置includesPropertyValuesfalse.

然而,当它运行时,当每个对象从上下文中删除时,错误就会被触发。添加日志记录如下:

// Fetch one object without property values
let f = NSFetchRequest<NSManagedObject>(entityName: "Entity")
f.includesPropertyValues = false
f.fetchLimit = 1

// Get the result from the fetch. This will be a fault
let firstEntity = try! context.fetch(f).first!

// Delete the object, watch whether the object is a fault before and after
print("pre-delete object is fault: \(firstEntity.isFault)")
context.delete(firstEntity)
print("post-delete object is fault: \(firstEntity.isFault)")
Run Code Online (Sandbox Code Playgroud)

产生输出:

pre-delete object is fault: true

post-delete object is fault: false

即使没有重写任何 CoreData 方法(willSave()prepareForDeletion()validateForUpdate()等),也会发生这种情况。我不知道还有什么可能导致这些故障发生。


更新:我在 Swift Playground 中创建了一个简单的示例。它具有具有单个属性的单个实体,并且没有关系。Playground 在主线程上删除了 an 的 viewContext 中的托管对象NSPersistentContainer,a 表明对象属性isFaulttrue变为false

Tom*_*ton 4

我认为权威的答案需要查看核心数据源代码。由于这不太可能实现,因此我认为这可能是必要的,原因如下。

  • 对于具有关系的实体,可能有必要检查关系以处理删除规则并维护数据完整性。例如,如果删除规则是“级联”,则有必要触发故障以确定应删除哪些相关实例。如果它是“无效”,则触发故障以找出哪些相关实例需要将其关系值设置为 nil。
  • 除了上述内容之外,具有关系的实体还需要对相关实例执行验证检查。例如,如果您删除具有使用“无效”删除规则的关系的对象,并且反向关系不是可选的,则反向关系的验证检查将失败。检查这一点可能会触发故障。
  • 二进制属性可以将数据自动存储在外部文件中(“允许外部存储”选项)。为了清理外部文件,可能需要触发故障,以便知道要删除哪个文件。

我认为所有这些都可以被优化掉。例如,如果实体没有关系并且没有使用外部存储的属性,则不要触发故障。然而,这是从外部看,无法访问源代码。可能还有其他原因需要触发故障。这似乎是有可能的。或者可能没有人尝试过这种优化,无论出于何种原因。这似乎不太可能,但却是可能的。

顺便说一句,我分叉了您的游乐场代码以获得一个不依赖于外部数据模型文件的版本,而是在代码中构建模型。