Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find or create unique Core Data entity

A common scenario for core data driven apps is getting a unique object out of the backing store. If the object with a certain unique property exists, return that one, if it doesn't return a newly create one. I found myself writing the same thing over and over, so I wrapped it in a convenience method. But this seems so trivial, am I reinventing the wheel here? Is there a simpler, out-of-the-box way to achieve this?

Cheers,
EP

+(id)uniqueEntityfForName:(NSString *)name 
                withValue:(id)value 
                   forKey:(NSString *)key
   inManagedObjectContext:(NSManagedObjectContext *)context {

    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];    
    request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];
    request.predicate = [NSPredicate predicateWithFormat:[key stringByAppendingString:@" == %@"], value];
    NSArray *result = [context executeFetchRequest:request error:nil];

    id entity = [result lastObject];
    if (entity == nil) {
        entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
        [entity setValue:value forKey:key];
    } else {
        entity = [result lastObject];
    }

    return entity;
}

I use this method like this:

SomeEntity *entity = [CDUtils uniqueEntityfForName:@"SomeEntity" withValue:@"foo" forKey:@"bar" inManagedObjectContext:context];
like image 971
epologee Avatar asked Feb 11 '11 21:02

epologee


People also ask

How do you make a Core Data attribute unique with constraints?

If you look in the Data Model inspector you'll see a field marked "Constraints" – click the + button at the bottom of that field. A new row will appear saying "comma,separated,properties". Click on that, hit Enter to make it editable, then type "sha" and hit Enter again. Make sure you press Cmd+S to save your changes!

What is an entity in Core Data?

An entity describes an object, including its name, attributes, and relationships.

How do I create a Core Data model?

Add a Core Data Model to an Existing ProjectChoose File > New > File and select the iOS platform tab. Scroll down to the Core Data section, select Data Model, and click Next. Name your model file, select its group and targets, and click Create.

What is Nsmanagedobjectcontext in Core Data?

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


2 Answers

Pretty standard. My core data entities have lots of methods like [aStudent enrollmentForId:(long long)idValue createIfMissing:YES].

I'd also like to plug mogenerator , which removes much pain from Core Data. Among other things, it generates a factory method for every fetch request defined in the data model. So making a fetch predicate in the model like, e.g,

thingies: thingyId == $forThingyId

yields a matching class method:

+(NSArray *)fetchThingies:(NSManagedObjectContext *)moc forThingyId:(id)thingyId

...which does the first half of what you've written up there. A wrapper like

-(Thingy*)thingyForIdValue:(long long)thingyId

is then trivial to write, in whatever class holds your managedObjectContext (eg. a "parent" entity, or app delegate, or whatever.)

like image 158
rgeorge Avatar answered Sep 27 '22 20:09

rgeorge


A more flexible solution is to use Blocks to let the caller to handle 3 situations when comparing two lists.

  1. Matching Sets
  2. Host unmatched sets
  3. Local unmatched sets

Therefore, there is no need to create similar functions when inserting in a syncing fashion or additions to the data store.

typedef void (^objectOperationBlock)(NSManagedObjectContext *context,
                                 NSDictionary *hostObjectData,
                                 NSManagedObject *localManagedObject);

- (void) insertUniquely:(NSArray *)rawDataArray 
                 entity:(NSString *)entity 
           matchedBlock:(objectOperationBlock)matchedOperation
     hostUnmatchedBlock:(objectOperationBlock)hostUnmatchedOperation
    localUnmatchedBlock:(objectOperationBlock)localUnmatchedOperation
                  error:(NSError **)outError;

A full implementation can be found here: http://emplementation.blogspot.com/2011/12/importing-data-into-core-data-while.html

like image 38
docchang Avatar answered Sep 27 '22 21:09

docchang