0

我遇到了一个问题,我只是想不出解决方案。

我的应用程序配置为使用 Core Data(使用 xCode 创建的 AppDelegate 中的模板代码),在后台线程中导入大量数据。问题是,如果我运行了大型导入,我在 UI 线程中对 Core Data 所做的所有更改都不会保存到存储(有时)。如果我不运行导入,所有数据都会正确保存,并且问题不一致,这是一个开/关问题,但我已将其追踪为导致问题的导入。

我的线程代码看起来像这样(简化)

-(void)startSynchronization{
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(startSync:) object:nil];
[self.thread start];
}


-(void)startSync{
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] init];  
[importContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
[importContext setUndoManager:nil];
... import a lot of code and create thousands of core data entities..

}

persistentStoreCoordinator(从现在开始的 PSC)是来自应用程序 AppDelegate 的 PSC,我认为这就是问题所在。我读到多个线程应该使用单独的 PSC,但是我如何创建一个 PSC 并将其分配给在 AppDelegate 模板代码中创建的核心数据文件?

导入后核心数据的读取工作正常,但是当我稍后将核心数据模型中的一个“文档”实体标记为我的最爱时,即使我调用保存,此更改也不会写入数据库我来自 AppDelegate 的上下文。

我以为全局 PSC 用于同步多个上下文,我的应用程序中的一个上下文,以及线程导入代码中的导入上下文?

如何确保导入代码和 UI 代码看到相同的更改,并且我的商店是一致的?

谢谢

/雅各布

4

1 回答 1

3

他们改进了多线程在 iOS 5/MacOS 10.7 中的工作方式。现在,多线程 Core Data 有三种模式NSConfinementConcurrencyTypeNSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType. 第一个是过去的工作方式,也是您正在使用的方式。我提到其他的,因为它们可能值得研究,并且因为术语在搜索时可能很有用。

对于线程限制方法,您可以为每个线程创建一个新的托管对象上下文,就像您正在做的那样。我认为在你的循环之后你正在调用save背景上下文。您缺少的步骤是响应NSManagedObjectContextDidSaveNotification. 来自苹果的文档

通常,在线程 A 上,您注册托管对象上下文保存通知,NSManagedObjectContextDidSaveNotification. 当您收到通知时,其用户信息字典包含在线程 B 上插入、删除和更新的托管对象的数组。但是,由于托管对象与不同的线程相关联,因此您不应直接访问它们。相反,您将通知作为参数传递给mergeChangesFromContextDidSaveNotification:(您将其发送到线程 A 上的上下文)。使用此方法,上下文能够安全地合并更改。

总而言之,您所做的是订阅该通知,当它发生时(并且您的选择器被调用),您只需调用mergeChangesFromContextDidSaveNotification:主线程的托管对象上下文,将通知对象传递给后一种方法,如下所示:

- (void)mergeChanges:(NSNotification *)notification 
{
    if (notification.object != self.context) {
        [self.context mergeChangesFromContextDidSaveNotification:notification];
    }

    return;
}

假设您已经订阅了通知,这self.context指的是您的主线程的托管对象上下文。那应该处理获取更新。

我在上面提到其他并发类型的原因是另一种进行并发的方法(如果您使用的是最新的操作系统)涉及父上下文和子上下文。您可以有一个在私有队列模式下运行的上下文,并将其父级设置为您的主要 MOC。当上下文有父上下文时,对子上下文的保存操作只是将其更改推送到父上下文,而不接触磁盘。这可能是您可以研究的另一种模式。

于 2012-05-30T08:06:46.243 回答