Question

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

Was it helpful?

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.

OTHER TIPS

Here's how you create a background thread while using core data:

dispatch_queue_t fetchQ = dispatch_queue_create("JSON Fetcher", NULL);
    dispatch_async(fetchQ, ^{
        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        context.parentContext = self.mainMOC;

        [context performBlock:^{
            // implement your own background code here

            NSError *error;
            if(![context save:&error]) {
                // handle error
            }
        }];
});

You also need to save the results so they get propagated to the mainMOC. Hope it helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top