当前位置: 动力学知识库 > 问答 > 编程问答 >

ios - Saving a temporary managed object context on a background queue

问题描述:

According to the Concurrency with Core Data Guide, you should not save a NSManagedObjectContext in a background thread, because it is possible for the app to quit before the save completes, since threads are detached.

If I'm understanding correctly, that means something like this is incorrect

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];

[tempContext performBlockAndWait:^{

//Do some processing

NSError* error;

[tempContext save:&error];

}];

});

My first instinct would be to just save the context on the main queue when it's finished, but managedObjectContexts are supposed to be thread safe. Is the following something that would solve the problem or is there a better solution?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];

[tempContext performBlockAndWait:^{

//Do some processing

}];

dispatch_async(dispatch_get_main_queue(), ^{

[tempContext performBlockAndWait:^{

NSError* error;

[tempContext save:&error];

}];

});

});

网友答案:

First:

In your first example:
The [context save:...] should be done in the context's performBlockAndWait: block.
Also, if you are using a background context, you could simply call its performBlock: method, as it is already use GCD for dispatching, so it will look something like:

NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
[tempContext performBlock:^{
    //Do some processing
    NSError* error;
    [tempContext save:&error];
}];

Secondly:

"Saving in a Background Thread is Error-prone" (as I know it and understand it) means:
You can save in the background, but it is NOT guaranteed that the save you called will run to completion if the application quit (the database would still be valid, or could be rolled back to a pre-partial-save state).
==>
If you use background save, don't assume that a save operation has completed between 2 application executions.

Thirdly (just to emphasise):
DON'T use a private-queue context without performBlock: or performBlockAndWait:
==>
Your second example will lead to unexpected behavior

分享给朋友:
您可能感兴趣的文章:
随机阅读: