3

在使用 Instruments 之后,我发现我的代码中有一个地方运行时间很长并且阻塞了我的 UI:大量核心数据获取(这是摄取大型 JSON 数据包和构建托管对象同时确保对象的过程的一部分)没有重复)。

虽然我的意图是将这个请求分解成更小的部分并连续处理它们,但这仅意味着我将分散这些提取 - 我预计效果将是应用程序中的小突发而不是长时间的打嗝。

我在 Apple 的文档和在线的各种博客文章中读到的所有内容都表明,Core Data 和并发类似于戳蜂箱。所以,我胆怯地坐下来试一试。以下是我想出的,如果有人更聪明地指出我确定我写过的任何错误,我将不胜感激。

下面发布的代码有效。我读到的东西让我害怕我肯定做错了什么。我觉得如果把别针从手榴弹中拔出来,我就在等它意外爆炸!

NSBlockOperation *downloadAllObjectContainers = [NSBlockOperation blockOperationWithBlock:^{
    NSArray *containers = [webServiceAPI findAllObjectContainers];
}];

[downloadAllObjectContainers setCompletionBlock:^{

    NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setPersistentStoreCoordinator:[_managedObjectContext persistentStoreCoordinator]];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification
                                                      object:backgroundContext
                                                       queue:[NSOperationQueue mainQueue]
                                                  usingBlock:^(NSNotification *note) {
                                                      [_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
                                                  }];


        Builder *builder = [[Builder alloc] init];
        [builder setManagedObjectContext:backgroundContext];

        for (ObjectContainer *objCont in containers) {  // This is the long running piece, it's roughly O(N^2) yuck!
            [builder buildCoreDataObjectsFromContainer:objCont];
        }

    NSError *backgroundContextSaveError = nil;
    if ([backgroundContext hasChanges]) {
        [backgroundContext save:&backgroundContextSaveError];
    }
}];

NSOperationQueue *background = [[NSOperationQueue alloc] init];
[background addOperation:downloadAllObjectContainers];
4

2 回答 2

6

由于您使用的是 NSPrivateQueueConcurrencyType,因此您必须为 iOS5 使用它,您不必费心在后台线程中创建上下文并将其合并到主线程中。

您只需要在主线程中创建一个并发类型为 NSPrivateQueueConcurrencyType 的托管对象上下文,并在传递给 managedObjectContext:performBlock 方法的块内对托管对象执行所有操作。

我建议你看看WWDC2011 session 303 - What's New in Core Data on iOS。另外,请查看iOS5 的核心数据发行说明

以下是发行说明中的​​引述:

NSManagedObjectContext 现在为并发操作提供结构化支持。当您使用 initWithConcurrencyType: 创建托管对象上下文时,您有三个选项用于其线程(队列)关联

限制(NSConfinementConcurrencyType)。

这是默认设置。您保证上下文不会被除您创建它的线程之外的任何线程使用。(这与您在以前的版本中使用的线程要求完全相同。)

专用队列 (NSPrivateQueueConcurrencyType)。

上下文创建和管理私有队列。与您创建和管理与上下文相关联的线程或队列不同,这里上下文拥有队列并为您管理所有细节(前提是您使用如下所述的基于块的方法)。

主队列(NSMainQueueConcurrencyType)。

上下文与主队列相关联,因此与应用程序的事件循环相关联,但它在其他方面类似于私有的基于队列的上下文。您将此队列类型用于链接到控制器和 UI 对象的上下文,这些对象只需要在主线程上使用。

于 2012-05-27T15:02:29.367 回答
0

并发

并发性是同时处理多个队列上的数据的能力。如果您选择使用 Core Data 的并发性,您还需要考虑应用程序环境。在大多数情况下,AppKit 和 UIKit 不是线程安全的。特别是在 OS X 中,Cocoa 绑定和控制器不是线程安全的核心数据、多线程和主线程

于 2017-03-15T12:12:00.303 回答