2012-05-27 29 views
3

使用Instruments之后,我发现我的代码中存在很长时间的运行并阻塞了我的用户界面:处理大量JSON数据包的一部分,建立管理对象,同时确保对象不被复制)。虽然我的意图是将这个请求分解为更小的部分并连续地处理它们,但这只意味着我将分散这些提取 - 我预计效果将是应用程序中的小动作,而不是一个漫长的打嗝。使用NSOperationQueues的核心数据和并发性

我在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]; 

回答

6

由于您使用NSPrivateQueueConcurrencyType你必须做它的iOS5,你不必去通过在后台线程创建上下文并在主线程合并它的所有的麻烦。

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

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

下面是从发行说明报价:

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

约束(NSConfinementConcurrencyType)。

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

专用队列(NSPrivateQueueConcurrencyType)。

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

主队列(NSMainQueueConcurrencyType)。

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

+0

我只在iOS 5上使用它。 “核心数据并发”文章没有提到这一点,我无法找到你在iOS 5.0 API Diffs中提出的建议。 NSManagedObjectContext的文档对于那些常量来说有点简洁。你能否指引我参考你参考的文档的方向? – edelaney05

+0

当然,我编辑了原帖以解答您的评论。 – svena

0

并发

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