iOS5で次のコードを同期しようとしています:
- オブジェクトには、画像へのURLなどのデータを取得するHTTPリクエストを作成するメソッドがあります
- データが到着すると、テキストデータを使用してCoreDataモデルにデータが入力されます
- 同時に、イメージをダウンロードするために2番目のスレッドが非同期でディスパッチされます。このスレッドは、画像がすでにキャッシュされてCoreDataモデルで使用可能になると、KVOを介してviewControllerにシグナルを送信します。
- 画像のダウンロードには時間がかかるため、画像以外のすべての属性を持つCoreDataオブジェクトを呼び出し元にすぐに返します。
- また、2番目のスレッドのダウンロードが完了すると、CoreDataモデルを保存できます。
これは(簡略化された)コードです:
- (void)insideSomeMethod
{
[SomeHTTPRequest withCompletionHandler:
^(id retrievedData)
{
if(!retrievedData)
{
handler(nil);
}
// Populate CoreData model with retrieved Data...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
handler(aCoreDataNSManagedObject);
[self shouldCommitChangesToModel];
}];
}
- (void)shouldCommitChangesToModel
{
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
}
しかし、何が起こっているのかというと、バリアベースの保存ブロックは常に画像読み込みブロックの前に実行されます。あれは、
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
前に実行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
したがって、明らかに私はバリアの前に画像読み込みブロックを実際にディスパッチしていません。そうしないと、バリアは画像読み込みブロックが完了するまで待機してから実行されます(これは私の意図でした)。
私は何が間違っているのですか?画像読み込みブロックがバリアブロックの前にキューに入れられていることを確認するにはどうすればよいですか?