为什么Core Data NSManagedObject在删除时会被触发?

时间:2018-03-01 22:36:12

标签: ios swift core-data nsmanagedobject nsmanagedobjectcontext

我正在尝试有效批量删除大量NSManagedObject s(不使用NSBatchDeleteRequest)。我一直在遵循this answer(适用于Swift)中的一般过程,通过批处理请求对象,删除,保存然后重置上下文的操作。我的抓取请求将includesPropertyValues设置为false

但是,当此操作运行时,在从上下文中删除每个对象的位置,将触发该错误。添加日志记录如下:

// 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)")

产生输出:

  

pre-delete object is fault: true

     

post-delete object is fault: false

即使没有任何CoreData方法的覆盖(willSave()prepareForDeletion()validateForUpdate()等),也会发生这种情况。我无法弄清楚还有什么可能导致这些错误发生。

更新:我在Swift游乐场中创建了simple example。这个实体只有一个属性,没有关系。操场从NSPersistentContainer的viewContext中删除主线程上的托管对象,演示对象属性isFaulttrue更改为false

2 个答案:

答案 0 :(得分:2)

我认为权威的答案需要查看核心数据源代码。由于这不太可能即将到来,我可以想到这可能是必要的一些原因。

  • 对于有关系的实体,可能需要检查处理删除规则和维护数据完整性的关系。例如,如果删除规则是&#34; cascade&#34;,则需要触发故障以确定应删除哪些相关实例。如果它&#34;取消&#34;,则触发故障以确定哪些相关实例需要将其关系值设置为nil。
  • 除上述内容外,具有关系的实体需要对相关实例执行验证检查。例如,如果删除具有使用&#34; nullify&#34;的关系的对象。删除规则,并且反向关系不是可选的,您将无法通过反向关系验证检查。检查这可能会触发故障。
  • 二进制属性可以将数据自动存储在外部文件中(&#34;允许外部存储&#34;选项)。为了清理外部文件,可能需要触发故障,以便知道要删除哪个文件。

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

BTW我将您的游乐场代码分叉以获取a version that doesn't rely on an external data model file,而是在代码中构建模型。

答案 1 :(得分:1)

Tom Harrington 最好地解释了它。 CoreData的内部实现显然需要在标记要从持久性存储中删除的对象时触发错误,就像访问对象的属性时一样。正如本answer中所述,“NSManagedObject始终是动态呈现的。因此,如果删除它,Core Data将排除数据”

这似乎是至少暂时的正常行为,而不是真正的问题。