使用NSOperationQueues的核心数据和并发 [英] Core Data and Concurrency using NSOperationQueues

查看:188
本文介绍了使用NSOperationQueues的核心数据和并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Instruments之后,我发现我的代码中的一个点是非常长的运行和阻塞我的UI:大量的核心数据提取(它是一个进程的一部分,摄取一个大的JSON数据包,并建立管理对象,同时确保对象没有重复)。

After using Instruments, I have found the a spot in my code that is very long running and blocking my UI: lots of Core Data fetches (it's part of a process of ingesting a large JSON packet and building up managed objects while making sure that objects have not be duplicated).

虽然我的意图是将这个请求分解成更小的部分并连续处理它们,但这只意味着我会分开这些提取 - 我预计的效果将是在应用程序的小爆发的急动,而不是一个长期打嗝。

While my intentions are to break up this request into smaller pieces and process them serially, that only means I'll be spreading out those fetches - I anticipate the effect will be small bursts of jerkiness in the app instead of one long hiccup.

我在苹果的文档和在线的各种阅读博客帖子表示核心数据和并发性类似于戳一个蜂箱。所以,胆小的我坐下来给它的ol的大学尝试。下面是我想出来的,我会感谢有人更清楚地指出任何错误,我相信我写了。

Everything I've read both in Apple's docs and online at various blog posts indicates that Core Data and concurrency is akin to poking a beehive. So, timidly I've sat down to give it the ol' college try. Below is what I've come up with, and I would appreciate someone wiser pointing out any errors I'm sure I've written.

下面的代码工作。我读过的内容让我恐惧,我一定做错了事;

The code posted below works. What I have read has me intimidated that I've surely done something wrong; I feel like if pulled the pin out of a grenade and am just waiting for it to go off unexpectedly!

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,你不必经历所有麻烦,在后台线程中创建上下文并将其合并到主线程。

Since you are using NSPrivateQueueConcurrencyType you must be doing it for iOS5, you do not have to go through all the trouble of creating context in a background thread and merging it in the main thread.

所有你需要的是创建一个托管在主线程中使用并发类型NSPrivateQueueConcurrencyType的对象上下文,并且在一个块内的被管理对象的所有操作传递到managedObjectContext:performBlock方法。

All you need is to create a managed object context with concurrency type NSPrivateQueueConcurrencyType in the main thread and do all operations with managed objects inside a block passed in to managedObjectContext:performBlock method.

我建议你看看 WWDC2011会话303 - iOS数据中的新功能
另外,请查看 iOS5的核心数据发行说明

以下是发行说明的引语:

Here's a quote from the release notes:


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

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

限制(NSConfinementConcurrencyType)。

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.)

私有队列(NSPrivateQueueConcurrencyType)。

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).

主队列(NSMainQueueConcurrencyType)

Main queue (NSMainQueueConcurrencyType).

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

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.

这篇关于使用NSOperationQueues的核心数据和并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆