NSPrivateQueueConcurrencyType
iOS 5では、MOCを初期化して取得することでバックグラウンドスレッドでデータを素早く取得する新しい方法が導入されました。performBlock:
Core Data の経験則の 1 つは、スレッド/キュー間で管理対象オブジェクトを共有できないというものです。 でも同じですか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 を使用する必要がありますか?
ベストアンサー1
使用する際にNSPrivateQueueConcurrencyType
必要なこと何でもその文脈に触れるまたはメソッド内のそのコンテキストに属する任意のオブジェクト-performBlock:
。
上記のコードは、オブジェクトをメイン キューに返しているため、不正です。ただし、新しい API を使用すると、この問題を解決できます。メイン キューに関連付けられたコンテキストを 1 つ作成します。つまり、次のようになりますNSMainQueueConcurrencyType
。
// 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 の配列をメイン スレッドのコンテキストに渡すこともできます。これはニーズによって異なります。