核心数据单一托管对象上下文和两个线程

Posted

技术标签:

【中文标题】核心数据单一托管对象上下文和两个线程【英文标题】:Core Data Single Managed Object Context and two threads 【发布时间】:2013-04-24 13:58:21 【问题描述】:

想弄清楚这一点我快疯了。我正在开发一个从网络服务器同步数据的应用程序。有一个后台线程将数据从服务器拉到应用程序。同时,我正在对 UI 进行更改。 UI 上更改的值正在保存到前台的核心数据中。

在整个应用程序中,我每次创建一个 fetchController 时都会从应用程序委托中获取一个 managedObjectContext 。应用委托代码

- (NSManagedObjectContext *)managedObjectContext

    if (__managedObjectContext != nil) 
        return __managedObjectContext;
    

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) 
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return __managedObjectContext;

现在的问题是我在尝试保存上下文时遇到错误。错误在代码中随机发生。一旦我对任何实体进行更改,我就会保存上下文。此外,我在每个实体中都有两种关系,一种是与它的孩子一对多,另一种与它的父母是对 - 一种。所有关系都有适当的逆。

我认为我在这里通过保持一个上下文在概念上做错了。您能否建议在后台和前台线程都在读取和写入 coredata 的情况下我应该如何管理上下文。谢谢。

【问题讨论】:

您正在使用线程限制初始化您的 MOC,因此您只能在创建它的线程上使用它……很可能是主线程。它本质上没有任何问题……但是您如何为后台保存创建 MOC?如果您使用的是相同的 MOC,那就是您的问题。阅读有关 Core Data 并发的文档。 【参考方案1】:

托管对象上下文不是线程安全的,因此如果您在多个线程上使用相同的上下文而不考虑并发性——您将遇到重大问题。例如,崩溃和/或数据丢失,甚至可能是数据损坏。有几种方法可以解决这个问题:

    在创建上下文时使用其中一种队列并发类型 - 请参阅 initWithConcurrencyType: 的文档。然后,每当您访问数据存储时,使用performBlock:performBlockAndWait: 来同步访问。

    为后台线程创建一个新的托管对象上下文。使用NSManagedObjectContextDidSaveNotificationmergeChangesFromContextDidSaveNotification: 保持多个上下文同步。

但无论你做什么,不要只在多个线程上使用一个托管对象上下文。

【讨论】:

以上是关于核心数据单一托管对象上下文和两个线程的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:我的托管对象上的托管对象上下文为零

Core Data 3 托管对象上下文

在后台和主线程中使用托管对象上下文

iPhone - 核心数据崩溃 - 多个托管对象上下文

在后台线程上安全保存 Core Data 托管对象上下文的正确方法?

核心数据错误与异常第 3 部分