objective-c - 使用 NSOperationQueues 的核心数据和并发

标签 objective-c ios5 core-data concurrency

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

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

我在 Apple 的文档和在线各种博客文章中阅读的所有内容都表明 Core Data 和并发性类似于戳 hive 。所以,我胆怯地坐下来给它上大学的机会。以下是我得出的结论,如果有人更明智地指出我确信我写下的任何错误,我将不胜感激。

下面发布的代码有效。我所读到的内容让我感到害怕,我肯定做错了什么;我感觉就像从手榴弹上拔出销子,然后就等着它出乎意料地爆炸!

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

最佳答案

由于您使用的是 NSPrivateQueueConcurrencyType,因此您必须为 iOS5 执行此操作,因此您不必经历在后台线程中创建上下文并将其合并到主线程中的所有麻烦。

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

我建议您看一下 WWDC2011 session 303 - What's New in Core Data on iOS。 另外,看看 Core Data Release Notes for iOS5 .

这是发行说明中的​​引述:

NSManagedObjectContext now provides structured support for concurrent operations. When you create a managed object context using initWithConcurrencyType:, you have three options for its thread (queue) association

Confinement (NSConfinementConcurrencyType).

This is the default. You promise that context will not be used by any thread other than the one on which you created it. (This is exactly the same threading requirement that you've used in previous releases.)

Private queue (NSPrivateQueueConcurrencyType).

The context creates and manages a private queue. Instead of you creating and managing a thread or queue with which a context is associated, here the context owns the queue and manages all the details for you (provided that you use the block-based methods as described below).

Main queue (NSMainQueueConcurrencyType).

The context is associated with the main queue, and as such is tied into the application’s event loop, but it is otherwise similar to a private queue-based context. You use this queue type for contexts linked to controllers and UI objects that are required to be used only on the main thread.

关于objective-c - 使用 NSOperationQueues 的核心数据和并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10770742/

相关文章:

ios - 如何将平移手势的 x 坐标映射到立方体的旋转?

iphone - iOS 5 核心数据卡住

ios - 如何在 UIImage (GPUImage) 的不同滤镜之间正确切换

objective-c - STAssertTrue无法正常工作

ios - Dispatch Queue 中的 CIFilters 在启用 ARC 的项目中导致内存问题

swift - CoreData 的 performBackgroundTask 方法崩溃

objective-c - Core Data 对相关对象的 NSSet 进行排序时出现问题

ios - 从中断的地方继续动画 - 核心动画

ios5 - OpenCV 2.4.3 未找到符号 : _objc_setProperty_nonatomic on iOS 5

sqlite - 如何在不使用 -wal 和 -shm 的情况下将 MOC 的内容保存到文件中?