Set 不适用于 NSManagedObject?

Set doesn't work for NSManagedObject?

我最近在我的程序中发现了它,重复没有停止,即使我使用了Set。 该对象称为类别,有两个变量。

import Foundation
import CoreData

extension Category {
    @NSManaged var name: String?
    @NSManaged var items: NSSet?
}
class Category: NSManagedObject {
    override var hashValue: Int {
    return name!.hashValue
    }
}
func == (left: Category, right: Category) -> Bool {
     return left.name == right.name
}

我已经覆盖了class中的hashValue: Int和==方法,但是Set仍然将它们视为两个对象。这是否意味着 Set 不适用于 NSManagedObjects 或者我还有一些事情需要完成?

这是我的单元测试代码:

    guard let cate1 = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: context) as? MyProgram.Category else { return }
    cate1.name = "Cate"
    cate1.items = nil
    guard let cate2 = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: context) as? MyProgram.Category else { return }
    cate2.name = "Cate"
    cate2.items = nil
    let combine = Set<MyProgram.Category>([cate1, cate2])
    assert(cate1.hashValue == cate2.hashValue)
    assert(combine.count == 1)

它会在最后一行代码处失败。 哪位知道原因的可以给我一些建议吗?

不幸的是,Core Data 无法实现您的尝试 托管对象。

  • 对于 NSObject 的子类,您必须覆盖 isEqual:hash(而不是 ==hashValue) , 请参阅 .

  • 对于NSManagedObject个子类,明确"forbidden"到 覆盖 isEqual:hash,请参阅 NSManagedObject Class Reference。原因是 您可以比较托管对象的相等性而无需检索它们的所有对象 来自持久存储的属性 ("fire a fault").

因此,您无法定义自己的 "equality" 概念 以与 Set 一起使用的方式为核心数据管理对象或 NSSet.

检查集合是否已经包含具有给定的托管对象 属性 你可以做类似的事情

if (combine.contains { [=10=].name == cate2.name }) {

}

为了避免具有相同名称的类别对象,您应该 执行获取请求,该请求检查是否具有给定的对象 名称已经存在。