My first question would be how do you plan to identify when two objects are using the same image? Is there a property on the image you can store and query to determine whether the image you're setting already exists? And how expensive, computationally, is that? If it takes a lot of time, you might end up optimizing for storage and impacting performance.
However, if you do have a way of doing this efficiently, you could create an ImageBlob
entity to do what you describe. The entity that uses ImageBlob
s should have an imageBlob
or imageBlobs
relationship with ImageBlob
. ImageBlob
should have an inverse relationship with a name like, for example, users
.
In your code, when you want to reuse an ImageBlob
, it's as simple as doing something like this:
NSManagedObject *blob = // get the image blob
NSManagedObject *user = // get the user
[user setValue:blob forKey:@"imageBlob"]; // do this if it uses a single image
[[user mutableSetValueForKey:@"imageBlobs"] addObject:blob]; // do this if it uses multiple images
Another consideration you'll want to think about is what to do with blobs that are no longer needed. Presumably, you want to drop any images that aren't being used. To do this, you can sign up your application delegate or NSPersistentDocument
subclass (depending on whether your app is document-based or not) for the NSManagedObjectContextObjectsDidChangeNotification
notification. Whenever the managed object context changes, you can delete any unneeded images like this:
- (void)managedObjectContextObjectsDidSave:(NSNotification *)notification {
NSManagedObjectContext *managedObjectContext = [notification object];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntity entityWithName:@"ImageBlob" inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"users.@count == 0"];
NSArray *unusedBlobs = [managedObjectContext executeFetchRequest:fetchRequest error:nil]; // Don't be stupid like me; catch and handle the error
[fetchRequest release];
for (NSManagedObject *blob in unusedBlobs) {
[managedObjectContext deleteObject:blob];
}
}