简体   繁体   English

-objectRegisteredForID:和--existingObjectWithID之间有什么区别:错误:?

[英]What's the difference between -objectRegisteredForID: and -existingObjectWithID:error:?

What's the difference between getting an managed object with 获取托管对象之间的区别是什么

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

and

- (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error

What are "registered" objects? 什么是“注册”对象? What's the difference between "registered" objects and "unregistered" objects? “已注册”对象和“未注册”对象之间有什么区别?

What are "registered" objects? 什么是“注册”对象?

Judging from the results I've gotten using these methods, a registered object is one that has been fetched into the MOC. 从我使用这些方法的结果来看,已注册的对象是已被提取到MOC中的对象。 If an object exists in the persistent store but has not been fetched, feeding its objectID to the objectRegisteredForID method will return nil. 如果对象存在于持久性存储中但尚未获取,则将其objectID提供给objectRegisteredForID方法将返回nil。

How could you even have its objectID if it had not been fetched? 如果没有提取它,你甚至可以拥有它的objectID? Well, I visited this question when implementing a Revert routine. 好吧,我在实现Revert例程时访问了这个问题。 I dumped any unsaved changes by replacing the database with an older copy, cleared the context and then reaccessed it. 我通过用旧版本替换数据库来转储任何未保存的更改,清除上下文然后重新访问它。 But I wanted to be able to restore the user's selection of objects to the cache of a table. 但我希望能够将用户选择的对象恢复到表的缓存中。 So, before doing the reversion, I stashed the objectIDs that the user had selected in an array. 因此,在进行返回之前,我隐藏了用户在数组中选择的objectID。 Then, after the reversion, I rebuilt the table cache using the stashed objectIDs. 然后,在返回之后,我使用stashed objectID重建了表缓存。

When I called objectRegisteredForID using these stashed objectIDs, it always returned nil. 当我使用这些stashed objectID调用objectRegisteredForID ,它总是返回nil。 (But if I tested this before getting a fresh context, it would return the corresponding object -- which at that point was a fetched, loaded object. Hence my inference as to the meaning of "registered.") (但是如果我获得一个新的上下文之前对它进行了测试,那么它将返回相应的对象 - 在那时它是一个被提取的,被加载的对象。因此我推断出“已注册”的含义。)

When I called objectWithID using these stashed objectIDs, everything was fine unless the object had been deleted post the last save, in which case it would no longer exist in the database and the invalid but non-nil return would cause exceptions later. 当我使用这些objectWithID objectID调用objectWithID ,一切都很好,除非在上次保存后删除了对象,在这种情况下它将不再存在于数据库中,并且无效但非nil返回将导致异常。

So I used existingObjectWithID:error . 所以我使用了existingObjectWithID:error If the object still existed, it would be returned. 如果对象仍然存在,则返回。 If it no longer existed, the return would be nil and the error's localizedDescription would be "Attempt to access an object not found in store." 如果它不再存在,则返回为零,错误的localizedDescription将为“尝试访问未在商店中找到的对象”。

Years after the fact: 事后数年:

As Wienke suspects, registered objects are those already in memory for that context. 正如Wienke所怀疑的那样,已注册的对象是那些已经在内存中的对象。 So objectRegisteredForID: will return an object only if somebody else has previously obtained that object. 因此objectRegisteredForID:只有在其他人之前已经获得该对象时才会返回一个对象。

objectWithID: will return an object if it currently exists in the persistent store. objectWithID:如果对象当前存在于持久性存储中,则返回该对象。

So the really important distinction is: 所以真正重要的区别是:

objectWithID may go to the persistent store. objectWithID可以转到持久性存储。

Note the corollary: objectWithID may have to perform a fetch. 注意推论: objectWithID可能必须执行获取。 That means locking the store. 这意味着锁定商店。 So: 所以:

  • if the store is already locked by somebody else, objectWithID may block, whereas objectRegisteredForID will never block; 如果商店已被其他人锁定,则objectWithID可能会阻止,而objectRegisteredForID将永远不会阻止; and
  • supposing you had an array of 30 object IDs and you performed objectWithID for each, you'd potentially do 30 separate trips to the store — it'd be much faster to check whether the objects are already registered and then, if any aren't, use an NSFetchRequest to get the rest. 假设你有一个包含30个对象ID的数组并且你为每个对象执行了objectWithID ,那么你可能会对商店进行30次单独的访问 - 检查这些对象是否已经注册然后,如果有的话,它会快得多,使用NSFetchRequest来完成其余的工作。 Notice that a self in X query can accept an array or set of object IDs to return actual objects even though that wouldn't technically exactly match the normal Objective-C meaning of 'self'. 请注意, self in X查询中的self in X可以接受一个或一组对象ID来返回实际对象,即使这在技术上并不完全符合'self'的正常Objective-C含义。

Falling back on NSFetchRequest is also generally preferable if you have any relationship paths you're going to need prefetched. 如果您有任何需要预取的关系路径,那么回退NSFetchRequest通常也是首选。 So there's potentially quite a lot of performance to be gained. 因此,可能会获得相当多的性能。

I was recently confused as to why registeredObject(for objectID: NSManagedObjectID) was returning nil, but there was a simple explanation: the NSManagedObject instances I fetched were not retained: I extracted the information I needed from them and let them be deallocated, which seems to "unregister" them from the managed object context, though they could easily be retrieved using other methods on NSManagedObjectContext . 我最近很困惑为什么registeredObject(for objectID: NSManagedObjectID)返回nil,但有一个简单的解释:我提取的NSManagedObject实例没有被保留:我从他们那里提取了我需要的信息并让它们被释放,这似乎从托管对象上下文中“取消注册”它们,尽管可以使用NSManagedObjectContext上的其他方法轻松地检索它们。 I find the CoreData documentation truly terrible: "registered" is just one of many distinctions that are not clearly explained. 我发现CoreData文档真的很糟糕:“注册”只是众多区别中没有明确解释的区别之一。

To your first question: 对于你的第一个问题:

objectRegisteredForID: is the quick & easy way to get the object -- it either returns your object or it returns nil letting you know that it could not. objectRegisteredForID:是获取对象的快捷方式 - 它可以返回你的对象,也可以返回nil,让你知道它不能。 You use this when you either already know why the result might be nil or you don't care. 当你已经知道为什么结果可能是零或者你不关心时,你就使用它。

existingObjectWithID:error: is similar, in that it returns either your object or nil but, in addition, if you pass an error parameter, it will tell you WHY it returned nil. existingObjectWithID:error:类似,因为它返回你的对象或nil,但是,如果你传递一个错误参数,它会告诉你为什么它返回nil。 You may want to do this if you plan to do any sort of error reporting (a log message or alert), or error handling (perhaps you plan to take different actions, depending on which kind of error is returned. 如果您计划进行任何类型的错误报告(日志消息或警报)或错误处理(或许您计划采取不同的操作,可能需要执行此操作,具体取决于返回的错误类型)。

EDIT : In addition (per docs), if there is not a managed object with the given ID already registered in the context, the corresponding object is faulted into the context. 编辑 :另外(每个文档),如果没有已在上下文中注册的给定ID的托管对象,则相应的对象会出现在上下文中。

I suggest that you break out the "what are registered objects?" 我建议你打破“什么是注册对象?” portion of your question to a separate question in order to facilitate both getting a better answer (based on the subject line matching the question) and to help future spelunkers who may come looking for an answer. 你的问题的一部分是一个单独的问题,以便于获得更好的答案(基于匹配问题的主题行),并帮助可能来寻找答案的未来的探险者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM