使用NSOperationQueues的核心数据和并发

时间:2012-05-27 00:20:00

标签: objective-c ios5 core-data concurrency

在使用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];

2 个答案:

答案 0 :(得分:6)

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

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

我建议你看一下 WWDC2011会话303 - iOS上核心数据的新功能。 另外,请查看Core Data Release Notes for iOS5

以下是发行说明的引用:

  

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

     

限制(NSConfinementConcurrencyType)。

     

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

     

专用队列(NSPrivateQueueConcurrencyType)。

     

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

     

主队列(NSMainQueueConcurrencyType)。

     

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

答案 1 :(得分:0)

<强>并发

并发是指同时处理多个队列中的数据的能力。如果选择与Core Data一起使用并发,则还需要考虑应用程序环境。在大多数情况下,AppKit和UIKit不是线程安全的。特别是在OS X中,Cocoa绑定和控制器不是线程安全的Core Data, Multithreading, and the Main Thread