我应该使用==或[NSManagedObject isEqual:]来比较同一上下文中的托管对象吗?

时间:2011-06-09 19:13:40

标签: objective-c cocoa core-data

假设变量A和B在同一个托管对象上下文中保存托管对象的实例。我需要确保它们与持久性存储中的相同“记录”相关联。 “核心数据编程指南”中关于Faulting and Uniquing的部分说:

  

核心数据确保在给定的托管对象上下文中 - 持久性存储中的条目仅与一个托管对象相关联。

由此看来,指针比较似乎足以达到我的目的。或者使用isEqual是否有意义:在同一个上下文中比较托管对象?

3 个答案:

答案 0 :(得分:20)

使用==确定两个指针是否指向同一个对象。使用-isEqual来确定两个对象是否“相等”,其中相等的概念取决于被比较的对象。 -isEqual:通常会比较-hash方法返回的值。我之前写过,如果两个托管对象包含相同的值,-isEqual:似乎可能返回true。那显然不对。在文档中有一些警告要确保可变对象的哈希值在集合中不会发生变化,并且知道给定对象是否在集合中可能很困难。似乎可以肯定,托管对象的哈希不依赖于该对象包含的数据,更可能是它连接到对象不可变的内容;对象的-objectID值似乎可能是候选者。

考虑到这一切,我改变了我的观点;-)。每条记录仅在给定的上下文中表示一次,因此==可能是安全的,但-isEqual:似乎更能表达您的意图。

答案 1 :(得分:18)

对于从单个托管对象上下文中检索的对象,指针比较很好,关于unquing引用的文档也是如此。

应该使用

ObjectID来测试托管对象上下文中的对象相等性。

isEqual不进行属性测试,因为它被记录为不会使对象出错。事实上,看看反汇编函数,它绝对只是一个指针比较。

因此,托管对象的相等性测试的语义只是“指向托管对象上下文中的同一对象(记录)”,并且将对不同上下文中的对象进行比较。

答案 2 :(得分:7)

警告:由于NSManagedObject isEqual比较objectID,如果一个实例使用临时objectID而另一个实例使用永久objectID,则比较可能会失败。

背景:创建NSManagedObject时,会为其分配一个临时objectID。当NSManagedObject实际持久存储到存储中时,它将转换为永久对象ID。如果打印objectID,您可以看到区别:

x-coredata:/// MyEntity / t03BF9735-A005-4ED9-96BA-462BD65FA25F118(临时ID)

x-coredata:// EB8922D9-DC06-4256-A21B-DFFD47D7E6DA / MyEntity / p3(永久身份证)

当objectID转换为permanent时,其他线程和集合中的NSManagedObject实例不会更新。因此,如果在具有临时objectID的情况下将NSManagedObject放入NSArray中,则在尝试查找具有永久objectID的对象时,使用containsObject等方法将失败。记住containsObject使用isEqual。

最后,一些有用的方法是NSManagedObjectID isTemporaryID和NSManagedObjectContext obtainPermanentIDsForObjects:error:。