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

Cha*_*pta 18 cocoa core-data objective-c

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

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

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

Cal*_*leb 20

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

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

  • 托管对象的`isEqual`操作相同的==,即它确定两个变量名是否指向内存中的同一实际对象.它不会尝试比较属性值.虽然`isEqual`是从NSObject继承的,但是比较被覆盖并自定义到每个特定的类层次结构.NSArray和NSString对于相等性有不同的测试.由于托管对象在其对象图中是唯一的,因此在任何有意义的意义上,两个托管对象都不会"相等".即使它们包含相同的值,它们仍然位于对象图中的不同位置. (8认同)
  • 通常同意`-isEqual:` - 需要注意的另一点是NSManagedObject的用户被强烈地明确告知不要覆盖`isEqual:`,per:'你不能覆盖的方法:NSManagedObject本身定制了NSObject的许多功能,以便托管对象可以正确地集成到Core Data基础结构中.Core Data依赖于NSManagedObject的以下方法的实现,因此您绝对不能覆盖:... isEqual:,hash,superclass,class,self,zone ... (3认同)
  • +1表示`objectID`.那个_could_就是`isEqual:`正在做什么 - 我从未想过这一点.我仍然没有把它标记为接受 - 我希望我们可以得到一个具体的答案:`isEqual:`完全适用于托管对象. (2认同)

Ste*_*mer 18

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

ObjectID 应该用于测试托管对象上下文中的对象相等性.

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

因此,托管对象的相等性测试的语义只是"指向托管对象上下文中的同一对象(记录)",并将比较不同上下文中的对象的false.


小智 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(永久ID)

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

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