Iphone 什么';是-objectRegisteredForID:和-existingObjectWithID:错误之间的区别吗?

Iphone 什么';是-objectRegisteredForID:和-existingObjectWithID:错误之间的区别吗?,iphone,core-data,Iphone,Core Data,获取托管对象与 - (NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID 及 什么是“注册”对象?“已注册”对象和“未注册”对象之间有什么区别?关于第一个问题: objectRegisteredForID:是获取对象的快捷方法——它要么返回您的对象,要么返回nil,让您知道它不能。当您已经知道结果可能为零或不在乎时,您可以使用此选项 existingObjectWithID:error:与此类似,它返回对象

获取托管对象与

- (NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID


什么是“注册”对象?“已注册”对象和“未注册”对象之间有什么区别?

关于第一个问题:

objectRegisteredForID:
是获取对象的快捷方法——它要么返回您的对象,要么返回nil,让您知道它不能。当您已经知道结果可能为零或不在乎时,您可以使用此选项

existingObjectWithID:error:
与此类似,它返回对象或nil,但是,如果传递错误参数,它将告诉您返回nil的原因。如果计划执行任何类型的错误报告(日志消息或警报)或错误处理(根据返回的错误类型,可能计划执行不同的操作),则可能需要执行此操作

编辑:此外(根据文档),如果上下文中没有已注册具有给定ID的托管对象,则上下文中会出现相应对象的故障

我建议您将问题中的“什么是注册对象?”部分拆分为一个单独的问题,以便于获得更好的答案(基于与问题匹配的主题线),并帮助未来可能前来寻找答案的探索者

什么是“注册”对象

从我使用这些方法得到的结果来看,已注册的对象是已提取到MOC中的对象。如果持久存储中存在一个对象,但尚未提取,则将其objectID提供给
objectRegisteredForID
方法将返回nil

如果它没有被获取,你怎么可能拥有它的objectID呢?嗯,我在实现还原例程时访问了这个问题。我通过用旧的副本替换数据库来转储任何未保存的更改,清除上下文,然后重新访问它。但是我希望能够将用户选择的对象还原到表的缓存中。因此,在执行恢复之前,我将用户选择的objectid隐藏在数组中。然后,在恢复之后,我使用隐藏的objectid重建表缓存

当我使用这些隐藏的objectid调用
objectRegisteredForID
时,它总是返回nil(但如果我在获取新的上下文之前进行了测试,它将返回相应的对象——此时它是一个已获取、已加载的对象。因此,我推断了“已注册”的含义。)

当我使用这些隐藏的objectid调用
objectWithID
时,一切都很好,除非对象在上次保存后被删除,在这种情况下,它将不再存在于数据库中,并且无效但非零的返回将在以后导致异常

因此,我使用了
existingObjectWithID:error
。如果对象仍然存在,它将被返回。如果它不再存在,返回值将为零,错误的本地化描述将是“尝试访问存储区中未找到的对象”。

事实发生后几年:

正如Wienke所怀疑的,已注册的对象是那些已经在该上下文的内存中的对象。因此,
objectRegisteredForID:
将仅在其他人以前获得该对象时返回该对象

objectWithID:
将返回一个对象(如果该对象当前存在于持久存储中)

因此,真正重要的区别是:

objectWithID
可以转到持久存储。

请注意推论:
objectWithID
可能必须执行提取。这意味着锁定存储。因此:

  • 如果存储已被其他人锁定,
    objectWithID
    可能会被阻止,而
    objectRegisteredForID
    将永远不会被阻止;以及
  • 假设您有一个包含30个对象ID的数组,并且为每个对象执行了
    objectWithID
    ,您可能会对存储进行30次单独的访问-检查对象是否已注册会快得多,如果有,则使用
    NSFetchRequest
    获取其余的对象。请注意
    self in X
    查询可以接受一个数组或一组对象ID来返回实际对象,即使这在技术上与“self”的正常Objective-C含义不完全匹配

如果您有任何需要预取的关系路径,则通常最好使用NSFetchRequest。因此,可能需要获得相当多的性能。

我最近不明白为什么
registeredObject(对于objectID:NSManagedObjectID)
返回nil,但有一个简单的解释:我获取的
NSManagedObject
实例没有保留:我从它们那里提取了我需要的信息,并让它们被释放,这似乎是“取消注册”虽然可以使用
NSManagedObjectContext
上的其他方法轻松地从托管对象上下文中检索它们,但我发现CoreData文档真的很糟糕:“已注册”这只是许多没有明确解释的区别之一。

这个特殊的洞穴探险者在这里搜索objectRegisteredForID。你的回答让我开始解决一个问题——谢谢。这个解决方案基本上回答了第二个问题,所以我把它贴在下面。这个答案是错误的。-objectRegisteredForID:y仅在对象已在上下文中注册时返回对象。
-existingObjectWithID:error:
将尝试获取尚未注册的对象。Kevin:虽然我的回答不完整(感谢添加错误引用),但我不认为这是“错的”或者应该使用-1。我将更新以包含错误信息。答案肯定是错误的。existingObjectWithID:error将从持久存储或父上下文加载对象。我们使用了obj
- (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error