2013-09-04 10 views
6

私のアプリケーションでは、コアデータストアからかなりのオブジェクトを取得しています。これにより、アプリケーションがフリーズし、すべてのUI入力がブロックされます。私はバックグラウンドでは、アプリケーションが応答している間に、データが利用可能なときにtableviewを更新しながらフェッチをしたいと思います。
新しいNSManagedObjectContextNSPrivateQueueConcurrencyTypeに設定し、それをメインMOCの子として作成しました。私の設定は、すべての処理がまだUIをフリーズしているように、すべてのメインキューで起こっていた古いコードとの応答性にほとんど違いがないように、私は希望のオブジェクトを返す間、コアデータのバックグラウンド処理がまだブロックされています。

これによると、子コンテキスト設定はUIの応答性を維持するのに役立ちませんが、これを読んでいるネットのどこにいても、メインキューを大量の処理から解放したい場合は移動する方法です。何か不足していますか?

NSManagedObjectContext *mainMOC = self.mainObjectContext; 
    NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

    [backgroundMOC setParentContext:mainMOC]; 
    [backgroundMOC performBlock:^{ 

     //query for objects 
     NSArray *results = [Product MR_findAllInContext:backgroundMOC]; 

      NSError *childError = nil; 
      [backgroundMOC save:&childError]; 

     if ([results count] > 0) { 
      //get objectIDs 
      NSMutableArray *objectIDs = [NSMutableArray array] 
      for (NSManagedObject *object in results) { 
      [objectIDs addObject:[object objectID]]; 
      } 

      [mainMOC performBlock:^{ 
       //refetch objects on the mainQueue 
       NSMutableArray *persons = [NSMutableArray array] 
       for (NSManagedObjectID *objectID in objectIDs) { 
       [persons addObject:(Person*)[mainMOC objectWithID:objectID]]; 
       } 
       //return result 
       if (self.callBack) 
       self.callBack(persons); 
      }]; 
     } 
    }]; 
+1

WWDC 2013のビデオ「コアデータのパフォーマンスの最適化とデバッグ」で、このことについて話し合うことをお勧めします。 –

+0

この場合、主なコンテキストがNSFetchedResutsControllerによってサポートされているUIを凍結するネストされたコンテキストについて、iOS 5にバグがありました。この[Core Dataのネストされた管理オブジェクトコンテキストと頻繁なデッドロックフリーズ](http ://stackoverflow.com/questions/11786436/core-data-nested-managed-object-contexts-and-frequent-deadlocks-freezes) – Leonardo

+0

あなたのコードが子コンテキストを使用してメインスレッド上で呼び出され、performBlockが役に立たない場合あなたの貼り付けられたコードがメインスレッド –

答えて

13

まず、MR_findAllInContext:が正確に何をしているかを知ることは役に立ちます。最良の解決策はこれをより効率的な方法で解決することです。述語はどのように見えますか?リクエストにバッチサイズを指定していますか?あなたが照会している属性にインデックスを使用しますか?あなたのデータセットのサイズは?詳細がなくてもより良い解決策があるかどうかは分かりません。

あなたは、ネストされたコンテキストがどのように機能するかについて非常に広範に誤解されているように見えます。

問題は、コンテキストの設定方法です。バックグラウンドコンテキストをメインコンテキストの子にするので、バックグラウンドコンテキストで行うことはすべて、メインコンテキストを "通過"する必要があります。

バックグラウンドコンテキストを保存すると、オブジェクトグラフのすべての変更がメインコンテキストにプッシュされ、変更を維持するために保存する必要があります。バックグラウンドコンテキストでフェッチ要求を行うと、メインコンテキストに転送され、永続ストアコーディネータに送信され、結果はバックグラウンドコンテキストと同時に返されます。バックグラウンドコンテキスト(フェッチまたはセーブ)のリクエストは、親コンテキストをロックし、メインコンテキストでリクエストを直接行う場合と同様にメインスレッドをブロックします。

メインスレッドコンテキストの背後にバックグラウンドコンテキストを追加しても、パフォーマンスは向上しません。ネストされたコンテキストは、このように使用されることはありません。

目的を達成するには、メインコンテキストとは独立したコンテキストでフェッチ要求を実行する必要があります。 PSCに直接関連付けられているバックグラウンドコンテキスト。この場合、フェッチ要求はPSCをロックします。つまり、この間にメインコンテキストで要求を実行すると、PSCのロック競合が原因でメインスレッドがブロックされます。しかし、少なくともメインスレッドは一般的にブロックされません。

結果のオブジェクトIDをメインコンテキストに渡し、オブジェクトをobjectWithID:で取得し、これらのオブジェクトにアクセスすると、PSCの行キャッシュに依拠してデータを保持することに注意してください早くして。最初にオブジェクトがフォールトになるため、行キャッシュにデータがない場合、コアデータはすべてのオブジェクトに対してディスクに移動する必要があります。これは非常に遅いでしょう。インストゥルメントでキャッシュのヒットとミスをチェックできます。

+0

私はあなたにすべてを借りています。 –

関連する問題