使用
获取托管对象之间的区别是什么- (NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID
和
- (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error
什么是“注册”对象? “已注册”对象和“未注册”对象之间有什么区别?
答案 0 :(得分:17)
什么是“注册”对象?
从我使用这些方法的结果来看,已注册的对象是获取到MOC中的对象。如果对象存在于持久性存储中但尚未获取,则将其objectID提供给objectRegisteredForID
方法将返回nil。
如果尚未提取 其它的objectID怎么办?好吧,我在实现Revert例程时访问了这个问题。我通过用旧版本替换数据库来转储任何未保存的更改,清除上下文然后重新访问它。但我希望能够将用户选择的对象恢复到表的缓存中。因此,在进行返回之前,我隐藏了用户在数组中选择的objectID。然后,在返回之后,我使用stashed objectIDs重建了表缓存。
当我使用这些隐藏的objectID调用objectRegisteredForID
时,它总是返回nil。 (但是如果我在获得一个新的上下文之前测试了这个,它将返回相应的对象 - 在那时它是一个获取的,加载的对象。因此我推断“已注册”的含义。 )
当我使用这些stashed objectID调用objectWithID
时,一切都很好,除非在上一次保存后删除了对象,在这种情况下它将不再存在于数据库中并且无效但非零返回将导致例外。
所以我使用了existingObjectWithID:error
。如果对象仍然存在,则返回。如果它不再存在,则返回为零,错误的localizedDescription将为“尝试访问在商店中找不到的对象。”
答案 1 :(得分:6)
事实之后的几年:
正如Wienke所怀疑的那样,已注册的对象是那些已经在内存中的对象。所以objectRegisteredForID:
只有在其他人之前已经获得该对象时才会返回一个对象。
objectWithID:
将返回一个对象,如果该对象当前存在于持久性存储中。
所以真正重要的区别是:
objectWithID
可能会转到持久商店。
注意推论:objectWithID
可能必须执行提取。这意味着锁定商店。所以:
objectWithID
可能会阻止,而objectRegisteredForID
将永远不会阻止;和objectWithID
,那么您可能会对商店进行30次单独的访问 - 检查对象是否会快得多已经注册,如果有的话,请使用NSFetchRequest
来完成剩下的工作。请注意,self in X
查询可以接受一个或一组对象ID来返回实际对象,即使这在技术上并不完全符合&self;#的正常Objective-C含义。 / LI>
如果您有任何需要预取的关系路径,那么回退NSFetchRequest通常也是首选。因此,可能会获得相当多的性能。
答案 2 :(得分:1)
关于你的第一个问题:
objectRegisteredForID:
是 quick&轻松获取对象的方式 - 它要么返回你的对象,要么返回nil让你知道它不能。当你已经知道为什么结果可能是零或你不关心时,你就使用它。
existingObjectWithID:error:
类似,因为它返回你的对象或nil,但是,如果你传递一个错误参数,它会告诉你为什么它返回了nil。如果您计划进行任何类型的错误报告(日志消息或警报)或错误处理(或许您计划采取不同的操作,可能需要执行此操作,具体取决于返回的错误类型。
编辑:另外(按文档),如果没有已在上下文中注册的给定ID的托管对象,则相应的对象会出现在上下文中。
我建议你打破“什么是注册对象?”你的问题的一部分是一个单独的问题,以便于获得更好的答案(基于与问题相匹配的主题),并帮助未来的探险者寻找答案。
答案 3 :(得分:1)
我最近对于为什么registeredObject(for objectID: NSManagedObjectID)
返回nil感到困惑,但有一个简单的解释:我提取的NSManagedObject
个实例未被保留:我从他们那里提取了我需要的信息并让他们被解除分配,似乎从托管对象上下文中“取消注册”它们,尽管可以使用NSManagedObjectContext
上的其他方法轻松检索它们。我发现CoreData文档真的很糟糕:“注册”只是众多区别中的一个,没有明确解释。