In my app, I'm using Core Data alongside an additional sqlite database that doesn't use Core Data. In this additional database, I have columns that store references to NSManagedObject
instances via each instance's NSManagedObjectID
.
I'm getting an instance's objectId
as a string for storage like this:
instance.objectID.URIRepresentation.absoluteString
This results in a string looking something like:
x-coredata://EE13EA1E-D5F4-4E38-986D-3F4B0B03AEE4/ClassName/p658
Which I can later use to fetch the NSManagedObject
instance like this:
[persistentStoreCoordinator managedObjectIDForURIRepresentation:[NSURL URLWithString:uriString]];
As these URI strings are verbose and contain redundant information, I would like to save just the unique aspect of each in order to conserve space in the db and improve query performance. So in the example above, just '658' rather than the whole URI string.
So the first question is: what's a good way to extract just the unique tail of an NSManagedObjectID
? And secondly, once I have that stored, how can I later use it to fetch the instance?
I would like to avoid string manipulation as that feels icky, but I'll consider it if it's the only way. My only confusion there is where the 'EE13EA1E-D5F4-4E38-986D-3F4B0B03AEE4' portion is coming from in the above example. How could I access that value in order to rebuild a valid URI?
You could try setting the "Allows External Storage" flag on the attributes that contain your large chunks of data, and see if that eliminates the need for a separate, directly-managed database.
Otherwise, URIRepresentation
returns an NSURL
, so no "icky" string manipulation is necessary. Just use the NSURL
methods. ;^) Here's how you break it down:
NSURL *instanceURL = instance.objectID.URIRepresentation;
NSURL *classURL = [instanceURL URLByDeletingLastPathComponent];
NSString *classString = [classURL absoluteString];
NSString *instanceId = [instanceURL lastPathComponent];
And here's how you put it back together later:
NSURL *reconstructedClassURL = [NSURL URLWithString:classString];
NSURL *reconstructedInstanceURL = [reconstructedClassURL
URLByAppendingPathComponent:instanceId];
NSManagedObjectID *objectID = [moc.persistentStoreCoordinator
managedObjectIDForURIRepresentation:reconstructedInstanceURL];
NSManagedObject *reconstructedInstance = [moc objectWithID:objectID];
Note that since the URIRepresentation
is documented to be "archivable", there's no harm in rebuilding one from components that were given to you by Core Data. Core Data doesn't know that you took it apart and put it back together.
However, Apple is allowed to change the format returned by URIRepresentation
in the future, as long as managedObjectIDForURIRepresentation:
continues accepting the old format. That means the code above that breaks apart the URIRepresentation
could stop working someday.
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