为什么我们需要调用 context.delete 从 NSManagedObject 数组中删除一个项目?

Why do we need to call context.delete to delete an item from NSManagedObject array?

假设我有;

var itemArray = [Item]()

并且 Item 是一个 NSManagedObject。 Item 有两个属性“Title”:String 和“Done”:Boolean。这是我的数据模型的图片。

//  Item+CoreDataClass.swift

//  This file was automatically generated and should not be edited.
//

 import Foundation
 import CoreData

 public class Item: NSManagedObject {

 }

当我更改 Done 的值并调用 context.save 时,它会自动反映到 Persistent Container。但是,当我说

从数组中删除一个元素时
itemArray.remove(at: someindex)

并调用 context.save。该项目不会从持久性容器中删除。只要我打电话,

context.delete(itemArray[someindex])

然后该项目真正从商店中删除。

那么为什么仅从 itemArray 中删除并保存上下文是不够的,尽管更改属性值和保存上下文足以在 Core Data 上成功进行 CRUD 操作?

数组var itemArray = [Item]()与底层数据库没有直接关系。因此从该数组中删除项目不会影响核心数据数据库。

要在 Core Data 数据库中创建、保存或删除 NSManagedObject 实例,您需要调用有效 NSManagedObjectContext 的相关函数。

对 CoreData 的任何操作都应通过 NSManagedObjectContext 完成,因为它是访问或更新数据库中任何实体的暂存器。因此,在您删除 Item 实体的情况下,您应该仅通过上下文来执行此操作以反映在数据库中。

var itemArray = [Item]()
let context = //get your context
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
let predicate = NSPredicate(format: " (primaryKey == %@) ", "your_primary_key")
fetchRequest.predicate = predicate
itemArray = try! context.fetch(fetchRequest)
for i in 0 ..< itemArray.count where i < itemArray.count-1 {
    context.delete(itemArray[i])
}

do {
    try context.save()
} catch {
    // print the error
}

当您更改 Item 对象的属性时,Core Data(实际上是 NSManagedObjectContext)会检测到,因为 Item 属于 NSManagedObjectContext 并且该项目被标记为脏。但是你的数组与 NSManagedObjectContext 没有任何联系,所以你对它所做的任何更改都不会被 NSManagedObjectContext 检测到,这就是为什么你需要明确地告诉它你想删除你从数组中删除的项目。

另一种看待它的方式是,您在 Core Data 模型中 create/define 的任何内容都为 NSManagedObjectContext 所知,但在 swift 代码之外创建的任何内容都是未知的。如果您开始处理实体之间的一对多关系,您会发现在一对多集合中添加或删除对象将由 NSManagedObjectContext 以您期望的数组方式直接处理。