ioscore-datansfetchrequestnsentitydescription

iOS: updating a core data db require a lot of time


In my project I should download a JSON file made in this way:

[{"id":"2","n":"One"},{"id":"2","n":"Two"},{"id":"2","n":"Three"},...]

my code is this:

- (void) startPopulate:(NSArray *)array{

    NSManagedObjectContext *context = [[self sharedAppDelegate] managedObjectContext];

    NSFetchRequest *fetchRequest=[NSFetchRequest fetchRequestWithEntityName:@"Myentity"];
    NSError *error = nil;

    for (id element in array){

        [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"id == %@",[element objectForKey:@"id"]]];
        Myentity *myE = [[context executeFetchRequest:fetchRequest error:&error] lastObject];

        //update
        if (myE != nil){

            myE.id_e = [element objectForKey:@"id"];
            myE.name = [element objectForKey:@"n"];
        }

        //new element
        else{

            Myentity *myE = [NSEntityDescription insertNewObjectForEntityForName:@"Myentity" inManagedObjectContext:context];
            myE.name = [element objectForKey:@"n"];
            myE.id_e = [element objectForKey:@"id"];
        }
    }

    if (![context save:&error]) {
        NSLog(@"couldn't save: %@", [error localizedDescription]);
    }
    else{

        NSLog(@"DB UPDATED");
    }
}

As you can see I pass at the method the array of dictionaries and I check if the entity exist or not. It work fine and I have not particulars problems. The 'problem', if it's the way to call it, is that I have 12000 element and this method run for about 53 seconds. It's very very slow. What type of solution can I adopt to make it more quick? Or I should just put this method inside a background process? thanks


Solution

  • Should you put it in a background process?

    Absolutely. Start a background thread and create a child context from your main context to do all the work in.

    What else can be done

    Every unsaved change you make to a managed object context is stored in memory. Making thousands of changes before saving is inadvisable as it will take a lot of memory but also the save take will take a long time.

    You could batch the updates into say 100 changes at a time and save each block of 100.

    Alternatives

    If you are always loading in these items for the app then you could also preload them into a DB and bundle it into the app itself.

    That way you don't need to save them at run time as they are already in there.