ios - 在后台队列中保存临时管理对象上下文

标签 ios multithreading core-data grand-central-dispatch nsmanagedobjectcontext

根据Concurrency with Core Data Guide ,您不应该在后台线程中保存 NSManagedObjectContext,因为应用程序可能会在保存完成之前退出,因为线程是分离的。

如果我没理解错,那就是说这样的事情是不正确的

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];
    }];
});

我的第一直觉是在完成时将上下文保存在主队列中,但 managedObjectContexts 应该是线程安全的。以下是可以解决问题的方法还是有更好的解决方案?

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];
        }];
    });
});

最佳答案

第一:

在第一个示例中:
[context save:...] 应在上下文的 performBlockAndWait: block 中完成。
另外,如果您使用后台上下文,您可以简单地调用其 performBlock: 方法,因为它已经使用 GCD 进行调度,因此它看起来像:

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

其次:

“在后台线程中保存很容易出错”(据我所知并理解)的意思是:
您可以在后台保存,但如果应用程序退出,则不能保证您调用的保存将运行完成(数据库仍然有效,或者可以回滚到部分保存前的状态)。
==>
如果您使用后台保存,请不要假设在两次应用程序执行之间已完成保存操作。

第三(只是为了强调):
不要使用没有 performBlock:performBlockAndWait:
的私有(private)队列上下文 ==>
你的第二个例子将导致意外的行为

关于ios - 在后台队列中保存临时管理对象上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19647854/

相关文章:

iphone - Core Data性能deleteObject并保存托管对象上下文

ios - AutoLayout View 使应用程序在 popViewController 上崩溃

ios - 发送 voip 推送通知后是否应关闭与 APNs 的连接?

java - Java中立即杀死线程

c++ - 带有 CWinThread 指针数组的 WaitForMultipleObjects

ios - Simperium 在向实体添加新属性时丢失数据

ios - 从核心数据中删除实体

ios - CBCentralManager:如何确定管理器正在扫描哪个外设

ios - 在没有 Xcode 的情况下,在 Flutter 中将 GoogleService-Info.plist 保存在哪里?

python - python 线程中这两种连接方法有什么区别?