Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data -existingObjectWithID:error: causes error 133000

My app uses Core Data (with some help of Magical Record) and is rather heavily multithreaded using NSOperation.

Of course I am very careful to only pass around NSManagedObjectID between threads/operations.

Now, to get back to the corresponding managed object in an operation, I use -existingObjectWithID:error: thus:

Collection *owner = (Collection *)[localContext existingObjectWithID:self.containerId error:&error];

But what I get back is nil and error says this is an error #13300: NSManagedObjectReferentialIntegrityError.

Here is what the documentation says about this error:

NSManagedObjectReferentialIntegrityError
Error code to denote an attempt to fire a fault pointing to an object that does not exist.
The store is accessible, but the object corresponding to the fault cannot be found.

Which is not true in my case: that object exists. Indeed, If I iterate through all instances of that Collection entity with an NSFetchRequest, I find it among them, and its NSManagedObjectID is exactly the one I passed to -existingObjectWithID:error:.

Moreover, if I use -objectWithID: instead, I get a correct object back just fine.

So there is something I'm missing. Here are a few additional observations/questions:

  • "an object that does not exist": what it the meaning of "exist" in that sentence? "exist" where? It definitely "exists" in my Core Data store at that point.
  • "the object corresponding to the fault cannot be found": what it the meaning of "found" in that sentence? "found" where? It definitely "be found" in my Core Data store at that point.

So maybe I am missing something regarding what existingObjectWithID:error: does? The documentation says:

If there is a managed object with the given ID already registered in the context, that object is returned directly; otherwise the corresponding object is faulted into the context.
[...]
Unlike objectWithID:, this method never returns a fault.

This doesn't help my issue. I don't mind getting my object fully faulted, and not a fault. In fact, any fault within it will fire on the next code line when I access the object properties.

  • What would be a realistic scenario leading to an NSManagedObjectReferentialIntegrityError?

Thanks for any enlightenment.

like image 413
Jean-Denis Muys Avatar asked Dec 26 '11 16:12

Jean-Denis Muys


People also ask

How do I delete all Core Data?

One approach to delete everything and reset Core Data is to destroy the persistent store. Deleting and re-creating the persistent store will delete all objects in Core Data.

Is Core Data thread safe?

Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.

What is Nsmanagedobjectcontext in Core Data?

An object space to manipulate and track changes to managed objects.

What is the purpose of Core Data?

Core Data is a framework that you use to manage the model layer objects in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence.


3 Answers

The problem is that NSManagedObjectID you pass is temporary. You can check it by calling NSManagedObjectID's isTemporaryID method. From docs:

Returns a Boolean value that indicates whether the receiver is temporary.

Most object IDs return NO. New objects inserted into a managed object context are assigned a temporary ID which is replaced with a permanent one once the object gets saved to a persistent store.

You should first save your changes to persistent store, only then get a permanent ID to pass to other context.

like image 84
Alexey Kozhevnikov Avatar answered Sep 21 '22 12:09

Alexey Kozhevnikov


When you're using multiple contexts, you need to make sure you save context A before passing a managed object ID from context A to another context B. Only after the save completes will that object be accessible from context B.

-objectWithID: will always return a non-nil object, but it will throw an exception once you start using it if there's no backing object in the store. -existingObjectWithID:error: will actually run some SQL and do I/O if that object isn't already registered with the context it's used on.

like image 44
Daniel Eggert Avatar answered Sep 21 '22 12:09

Daniel Eggert


NSManagedObjectReferentialIntegrityError = 133000

NSManagedObjectReferentialIntegrityError Error code to denote an attempt to fire a fault pointing to an object that does not exist. The store is accessible, but the object corresponding to the fault cannot be found. Available in Mac OS X v10.4 and later. Declared in CoreDataErrors.h.

See this documentation.

This tutorial might be helpful to you.

So the probable reason is you are trying to fetch the object which is non existing. This happens generally when you try to create an objectid for a non existing object. The objectid will be returned to you and when try to get the object with this objectId you are thrown this exception.

like image 2
Madhup Singh Yadav Avatar answered Sep 19 '22 12:09

Madhup Singh Yadav