CoreData INSERT or REPLACE?

10,207

Solution 1

Remember, Core Data is an object hierarchy that happens to persist to a DB so you need to look at it like an object graph and not a database.

Therefore, yes you need to check to see if the object exists already using some defined unique ID and if it does not currently exist you need to create the new object vs. updating the existing object.

update

You don't need to fetch all of the objects, search the store using a NSFetchRequest and a NSPredicate to check for existence; if it exists update, if it doesn't create it.

Solution 2

Basically we order the inserted(fetched) data and the json data so at every index, they have equal values. We then retrieve the value at the respective index and update the managed object and in the case the counter is larger than the fetched results length, we insert a new managed object.

//Add JSON objects into entity

- (void) insertUpdate:(NSArray *)jsonArrayData {

    //sort JSON Data

    NSSortDescriptor *idDescriptor = [[NSSortDescriptor alloc] initWithKey:@"entityID" ascending:YES selector:@selector(localizedStandardCompare:)];
    NSArray *sortDescriptors = @[idDescriptor];
    NSArray *sortedJSONArray = [jsonArrayData sortedArrayUsingDescriptors:sortDescriptors];


    //get entity
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:self.managedObjectContext];

    // Get the ids from json in sorted order.
    NSMutableArray *entityIDs = [[NSMutableArray alloc]init];

    for (NSDictionary *jsonValues in jsonArrayData) {

        id value = [jsonValues objectForKey:@"entityID"];

        [entityIDs addObject:value];
    }

    //sort to make sure json and fetched data are both sorted in same manner
    [entityIDs sortUsingSelector:@selector(compare:)];


    // create the fetch request to get all Entities matching the IDs
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:entity];

    NSString *filter = @"(%K IN %@)";

    [fetchRequest setPredicate: [NSPredicate predicateWithFormat: filter, @"entityID", entityIDs]];

    // Make sure the results are sorted as well.
    [fetchRequest setSortDescriptors:
     @[ [[NSSortDescriptor alloc] initWithKey: idName ascending:YES] ]];

    // Execute the fetch.

    NSError *fetchError;
    NSArray *entityMatchingNames = [self.elRehabCoreData.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];


    int i = 0;

    //loop over JSONData
    for (NSDictionary *keyedValues in sortedJSONArray) {


        id value = [keyedValues objectForKey:@"entityID";

        //Create NSManagedObject
        NSManagedObject *managedObject = nil;
        int updateInsert = 0;


        if(entityMatchingNames.count > i ){
            //update
            managedObject = [entityMatchingNames objectAtIndex:i];

            if ([[managedObject valueForKey:@"entityID"] isEqual:[keyedValues valueForKey:@"entityID"]]){

                updateInsert = 1;
            }

        }else{
            //insert
            managedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
            updateInsert = 1;
        }

        i++;

        //set value if updateInsert is true
       // The updateInsert flag is an extra security to make sure we only update when the value in JSON data is equal that of fetched data

        if (updateInsert) {
            [managedObject setValue:value forKey:attribute];
        }


    }
     //save core data stack
     [self saveContext];

}
Share:
10,207
Nyx0uf
Author by

Nyx0uf

Updated on June 16, 2022

Comments

  • Nyx0uf
    Nyx0uf over 1 year

    I'am currently migrating an iphone application using SQLite to CoreData.

    I need to do an INSERT or REPLACE to add only the new content, is there a way to do this or do I have to fetch all the DB and look for existing objects and add the new ones ?

    Thanks.