ArisRS
ArisRS

Reputation: 1394

CoreData and dispatch_async using Object from main managedObjectContext

I need to change some entities from the background thread, so I do the following:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSManagedObjectContext *parent = [Default managedObjectContext];
    NSManagedObjectContext *editContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:parent.concurrencyType];
    [editContext setPersistentStoreCoordinator:[Default persistentStoreCoordinator]];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(saveChanges:)
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:editContext];

    NSFetchRequest *request = [NSFetchRequest new];
    ...
    NSArray *fetchedObjects = [context executeFetchRequest:request error:nil];

    NSError *error;
    [editContext save:&error]
});

It is working, but sometimes it stops working, just exits from function on executeFetchRequest:request. It is happened on simulator. So Is it correct method for changing data from background thread?

Upvotes: 0

Views: 914

Answers (1)

danypata
danypata

Reputation: 10175

Yes, you can change data from a background thread into core data, but as a golden rule "every thread should have his own instance of NSManagedObjectContext" with the same persistentStoreCoordinator because in this way you are avoiding deadlocks on the database and other nasty problems.

But I see in your code some problems, I don't know if are editing mistakes or real mistakes.

  1. context that you are using for the fetch request is not used.
  2. You should remove the saveChanges observer after the save has been performed. (You don't want to be notified by other changes)
  3. Using self in a block is kind of a bad practice (not your case here) because it can lead to retain cycle. You should use __block YoirClass *blocksafeSelf = self;

Also it's hard to know what can be the problem here without an error, so you should pass the error parameter to the fetchRequest and check it if there is an error or not.

Also make sure that that it is really exiting the function, because in the case of deadlocks it's look like is exiting but in fact it's just stop at the line and waiting.

Upvotes: 1

Related Questions