Search code examples
objective-ccore-datansmanagedobjectnsmanagedobjectcontext

Coredata CRUD operations in background thread?


I am using the following code snippets from apple for Create/Update NSManagedObject in my application

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Add code here to do background processing
    //
    //

NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [private setParentContext:mainMoc];

        [private performBlock:^{
            for (NSDictionary *jsonObject in jsonArray) {
                NSManagedObject *mo = …; //Managed object that matches the incoming JSON structure
                //update MO with data from the dictionary
            }
            NSError *error = nil;
            if (![private save:&error]) {
                NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
                abort();
            }
            [mainMoc performBlockAndWait:^{
                NSError *error = nil;
                if (![mainMoc save:&error]) {
                    NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
                    abort();
                }
            }];
        }];




    dispatch_async( dispatch_get_main_queue(), ^{
        // Add code here to update the UI/send notifications based on the
        // results of the background processing
    });
});

I have two doubts

  1. For just reading the values from my model using the above code,

    [private performBlock:^{}); is required ?

  2. Is there any better approach for Create/Update opertaions in background thread. Am I using the best approach for mentioned operations ?

Thanks in advance


Solution

  • From Apple's Documentations Concurrency

    performBlock: and performBlockAndWait: ensure the block operations are executed on the queue specified for the context. The performBlock: method returns immediately and the context executes the block methods on its own thread. With the performBlockAndWait: method, the context still executes the block methods on its own thread, but the method doesn’t return until the block is executed.

    When you use NSPrivateQueueConcurrencyType, the context creates and manages a private queue.

    So you do not need to create another dispatch queue if you use performBlock: because it is asynchronously executes operations within block. Otherwise, if you use performBlockAndWait: which wait until to finish it's operation execution and in this case you should use another dispatch queue.

    Therefore, best practice is to avoid the use of another dispatch queue. e.g

    NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [private setParentContext:mainMoc];
    
    [private performBlock:^{
        for (NSDictionary *jsonObject in jsonArray) {
            NSManagedObject *mo = …; //Managed object that matches the incoming JSON structure
            //update MO with data from the dictionary
        }
        NSError *error = nil;
        if (![private save:&error]) {
            NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
            abort();
        }
        [mainMoc performBlockAndWait:^{
            NSError *error = nil;
            if (![mainMoc save:&error]) {
                NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
                abort();
            }
        }];
    }];