使用NSOperationQueues的核心数据和并发

ede*_*y05 3 concurrency core-data objective-c ios5

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

虽然我的目的是将这个请求分解成更小的部分并按顺序处理它们,但这只意味着我将分散这些内容 - 我预计效果将是应用程序中的一小部分急动而不是一次长时间的打嗝.

我在Apple的文档和在线各种博客文章中都读过的所有内容都表明,核心数据和并发性类似于挖掘蜂巢.所以,胆怯地我坐下来给它上大学的尝试.以下是我提出的内容,我希望有人能够指出我确定写过的任何错误.

下面发布的代码有效.我读过的内容让我感到害怕,我肯定做错了什么; 我觉得如果把针从手榴弹中拔出来,我只是等着它意外地走了!

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];
Run Code Online (Sandbox Code Playgroud)

sve*_*ena 6

由于你使用的是NSPrivateQueueConcurrencyType,你必须为iOS5做这件事,你不必经历在后台线程中创建上下文并在主线程中合并它的所有麻烦.

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

我建议你看看WWDC2011会议303 - iOS上核心数据的新功能.另外,请查看适用于iOS5的Core Data发行说明.

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

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

限制(NSConfinementConcurrencyType).

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

专用队列(NSPrivateQueueConcurrencyType).

上下文创建并管理专用队列.您不是创建和管理与上下文关联的线程或队列,而是拥有队列并管理您的所有详细信息(前提是您使用如下所述的基于块的方法).

主队列(NSMainQueueConcurrencyType).

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