I'm not really sure whether the format of this question is good for this site.
Basically, does anyone know what has convinced Apple to make the design decision that NSManagedObjectID changes whenever you save the data to the persistent store?
I might be wrong, but that decision sounds quite questionable to me. There is no clear advantage (it's an UUID! It is unique!), and yet it makes passing objectID's --- it can change under your feet at any time when the object is saved.
It is a big problem for me because I use three MOC system (background MOC -> UI MOC -> Persistent MOC), objects are inserted into the background MOC and propagated upwards with a save. The save is asynchronous, as it has to propagate over three different MOCs and returning objects after they were created, yet before they are saved to the persistent store is quite painful, as I can't rely on passing objectID around.
Am I doing something particularly wrong? Does anyone know what is the advantage of UUID being mutable anytime with no notification?
My biggest question is why temporary managedObjectID is offered at all. Is there any point in it at all? Is it just to confuse people into attempting to use it?
I'm a little confused why you keep saying the NSManagedObjectID
is specifically a UUID. The URI representation may have a similar appearance to the UUID format, but I don't see anywhere in the docs that it says that "a NSManagedObjectID
is a UUID" (and as I'll discuss below, it is more than that). Why exactly Apple designed it this way is beyond the scope of StackOverflow, so hopefully your question is really "what is Core Data's design, and how do I work with it?"
What the docs say (in Managed Object IDs and URIs) is that if you want to do this kind of object tracking, you should add your own UUID as a property:
You can sometimes benefit from creating your own unique ID (UUID) property which can be defined and set for newly inserted objects. This allows you to efficiently locate specific objects using predicates (though before a save operation new objects can be found only in their original context).
The reason that the NSManagedObjectID
changes can be seen from the immutable data structure. It includes a persistentStore
property. This cannot be known for certain until you actually save the object (you might call assignObject:toPersistentStore:
for instance). Again, don't think of the NSManagedObjectID
in terms of its URI representation; that's just a serialization format. The real ID includes the persistent store, as indicated in the docs:
Like the primary key in the database, an identifier contains the information needed to exactly describe an object in a persistent store, although the detailed information is not exposed.
That identifier cannot be finalized until the object is inserted.
I'm not by any means an expert on Core Data, but my understanding is that the NSManagedObjectID
is guaranteed to be unique under most circumstances. The exceptions are:
isTemporaryId
.Since you're talking about a single lifecycle, I assume we're looking at the first option. If that's the case, you should wait to get the id until after your changes have propagated up to the persistent store. I think you can get the id from the same object, i.e. create the object, retain a pointer to it, save the context, then get that object's id from the retained pointer. Caveat: I've never actually done this, it's just my conclusion based on my reading of the documentation.
Also, the temporary id should persist until you save the context, so you should only ever have to worry about this once -- after the first time the new object's context is saved.
Incidentally, it seems to me that CoreData must be implemented in this way. If they attempted to guarantee that the id was unique before actually inserting it into the persistent store, what would happen if two different contexts grabbed the same id, before committing? The only way to guarantee uniqueness / prevent a sort of race condition for ids is to find a unique id when inserting the record into the database... Otherwise, CoreData would have to somehow insert a dummy value for each record a child context inserts...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With