2011-12-26 17 views
35

のiOS 5の間でオブジェクトを共有するには、迅速NSPrivateQueueConcurrencyTypeを使用してMOCを初期化して、コアの親指のルールのperformBlock:コアデータのNSPrivateQueueConcurrencyTypeとスレッド

にフェッチいずれかを実行して、バックグラウンドスレッドでデータをフェッチするための新しい方法を導入しましたデータはスレッド/キュー間で管理対象オブジェクトを共有できないというデータでした。 performBlock:の場合はまだですか?

[context performBlock:^{ 
    // fetch request code 

    NSArray *results = [context executeFetchRequest:request error:nil]; 

    dispatch_async(dispatch_get_main_queue(), ^(void) { 
     Class *firstObject = [results objectAtIndex:0]; 
     // do something with firstObject 
    }); 
}]; 

私は結果配列/オブジェクトをbgキューとメインキューの間で共有しているため、依然として受け入れられません。それには管理オブジェクトIDを使用する必要がありますか?

答えて

64

あなたがNSPrivateQueueConcurrencyTypeを使用するときは、その文脈または-performBlock:メソッド内でそのコンテキストに属する任意のオブジェクトに触れるを行う必要があります。

これらのオブジェクトをメインキューに戻すので、上記のコードは不正です。新しいAPIはしかし、この解決に役立ちます:あなたはNSMainQueueConcurrencyTypeでメインキューに関連付けられた1つの文脈、すなわちを作成します。

// Assume we have these two context (They need to be set up. Assume they are.) 
NSManagedObjectContext *mainMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease]; 
NSManagedObjectContext *backgroundMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; 

// Now this can safely be called from ANY thread: 
[backgroundMOC performBlock:^{ 
    NSArray *results = [backgroundMOC executeFetchRequest:request error:nil]; 
    for (NSManagedObject *mo in results) { 
     NSManagedObjectID *moid = [mo objectID]; 
     [mainMOC performBlock:^{ 
      NSManagedObject *mainMO = [mainMOC objectWithID:moid]; 
      // Do stuff with 'mainMO'. Be careful NOT to use 'mo'. 
     }]; 
    } 
}]; 

あなたは、独自のメソッドにインナー[mainMOC performBlock:]コールを移動する場合、これはあまり混乱を取得します。各オブジェクトIDのブロックを実行する代わりに、メインスレッドのコンテキストにオブジェクトIDの配列を戻したい場合もあります。それはあなたのニーズに依存します。

+0

この情報のソースはどのようなものですか?これは確かに私がそうであると予想されるものですが、Appleのマニュアルではブロック内でMOC操作を行わなければならないと述べています。ブロック内に作成されたMOについては明示的ではありません。 –

+14

MOはコンテキストに属します。それらはスレッドセーフではないため、属しているコンテキストのキュー内でのみ触れなければなりません。それはドキュメントからはっきりとしたものではありませんが、それはそれが言うことです。私はコアデータチームからこの情報を得ました。 –

+0

ドキュメントはどこですか?誰でもリンクがありますか? – djskinner

3

Daniel Eggertが説明しているように、これは間違いありません。例外はNSMainQueueConcurrencyTypeであり、メインスレッド(およびperformBlockメカニズムを介して他のスレッドからも)で管理対象オブジェクトのコンテキストとオブジェクトを安全に使用することができます。これの有用性は控えめではありません!

iOS 5では親コンテキストの概念も導入され、バックグラウンド操作が大幅に簡素化され、通知を使用してスレッド間の変更を伝える心配がなくなりました。

WWDC 2012 video "Session 214 - Core Data Best Practices"は、両方のテーマについてさらに詳しく説明しており、非常に包括的です。このビデオは、Core Dataを使用するすべての人にとって不可欠なものです。

+1

私が知る限り、NSMainQueueConcurrencyTypeは、メインスレッドからNSManagedObjectContextを作成することと同等であり、他のどのコンテキストよりもスレッドセーフではありません。あなたはどこから他のスレッドからperformBlockメカニズムを使ってそれを使うことができるのですか? – nevyn

+0

@ nevyn WWDC 2012ビデオ「セッション214 - コアデータのベストプラクティス」 - [NSManagedObjectContext performBlock:]は私が言及している正確なメカニズムです。 – JosephH

+0

これはNSManagedOBjectContextのドキュメントにもあります。「コードがメインスレッドで実行されている場合は、ブロックベースのAPIを使用する代わりにメインキュースタイルのコンテキストでメソッドを直接呼び出すことができます。 – ctietze

関連する問題