3

Instruments を使用した後、非常に長時間実行され、UI をブロックしているコード内のスポットを見つけました: 大量のコア データ フェッチ (これは、大きな JSON パケットを取り込み、管理対象オブジェクトを構築するプロセスの一部です。重複していません)。

私の意図は、このリクエストを小さな断片に分割して順次処理することですが、それは単にそれらのフェッチを分散させることを意味します - その効果は、1 回の長いしゃっくりではなく、アプリでの小さなジャーキネスの爆発になると予想しています.

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

2 に答える 2

6

NSPrivateQueueConcurrencyType を使用しているため、iOS5 で行う必要があります。バックグラウンド スレッドでコンテキストを作成し、それをメイン スレッドでマージするというすべての問題を経験する必要はありません。

必要なのは、メイン スレッドでコンカレンシー タイプ NSPrivateQueueConcurrencyType を使用してマネージド オブジェクト コンテキストを作成し、managedObjectContext:performBlock メソッドに渡されたブロック内のマネージド オブジェクトですべての操作を行うことだけです。

WWDC2011 セッション 303 - What's New in Core Data on iOSをご覧になることをお勧めします。また、iOS5 の Core Data Release Notes もご覧ください。

以下はリリースノートからの引用です。

NSManagedObjectContext は、同時操作の構造化サポートを提供するようになりました。initWithConcurrencyType: を使用して管理オブジェクト コンテキストを作成する場合、そのスレッド (キュー) の関連付けには 3 つのオプションがあります。

監禁 (NSConfinementConcurrencyType)。

これがデフォルトです。作成したスレッド以外のスレッドではコンテキストが使用されないことを約束します。(これは、以前のリリースで使用したものとまったく同じスレッド要件です。)

プライベート キュー (NSPrivateQueueConcurrencyType)。

コンテキストは、プライベート キューを作成および管理します。コンテキストが関連付けられているスレッドまたはキューを作成して管理する代わりに、ここではコンテキストがキューを所有し、すべての詳細を管理します (以下で説明するブロックベースのメソッドを使用する場合)。

メイン キュー (NSMainQueueConcurrencyType)。

コンテキストはメイン キューに関連付けられているため、アプリケーションのイベント ループに関連付けられていますが、それ以外はプライベート キュー ベースのコンテキストに似ています。このキュー タイプは、メイン スレッドでのみ使用する必要があるコントローラーと UI オブジェクトにリンクされたコンテキストに使用します。

于 2012-05-27T15:02:29.367 に答える