Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a concise form of NSManagedObjectID URI?

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?

like image 691
Dane Avatar asked Mar 12 '13 06:03

Dane


1 Answers

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.

like image 199
rob mayoff Avatar answered Nov 12 '22 15:11

rob mayoff