Search code examples
iosobjective-cxcodecore-data

Handling duplicate entries in Core Data


I have an app that allows users to save favorites. I am using Core Data to store the favorites as managed objects. I have written some code to prevent the possibility of storing duplicates, but am wondering if there is a better way to do so. Each favorite object has an ID field that is unique. In the following code I am simply looping through and checking the ID field, and if the value already exists, setting a flag value to true, and breaking out of the loop.

-(BOOL)addFavorite{
    BOOL entityExists = NO;
    if(context){
        // does this favorite already exist?
        NSArray *allFaves = [AppDataAccess getAllFavorites];
        for(Favorite *f in allFaves){
            if([f.stationIdentifier isEqualToString:stID]){
                entityExists = YES;
                break;
            }
        }
        if(!entityExists){
            NSError *err = nil;
            Favorite *fave = [Favorite insertInManagedObjectContext:context];
            fave.stationRealName = riverGauge.name;
            fave.stationIdentifier = stID;
            fave.stationState = @"WV";
            if(![context save:&err]){
                NSLog(@"ERROR: Could not save context--%@", err);
            }
            return YES;            
        }
    return NO;
}

I was wondering if Core Data has the ability to check to see if an object being added is a duplicate. Is there a predicate that can handle checking for duplicates? Thanks!


Solution

  • CoreData does no uniquing by itself. It has no notion of two entries being identical.

    To enable such a behavior you have to implement it yourself by doing a 'search before insert' aka a 'fetch before create'.

    NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Favorite"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stationIdentifier == %@", stID];
    [fetch setPredicate:predicate];
    YourObject *obj = [ctx executeRequest:fetch];
    
    if(!obj) {
        //not there so create it and save
        obj = [ctx insertNewManagedObjectForEntity:@"Favorite"]; //typed inline, dont know actual method
        obj.stationIdentifier = stID;
        [ctx save];
    }
    
    //use obj... e.g.
    NSLog(@"%@", obj.stationIdentifier);
    

    Remember this assumes single-threaded access