【发布时间】:2012-06-04 05:27:15
【问题描述】:
我正在尝试在 iOS5 中同步以下代码:
- 一个对象有一个方法可以发出一个HTTP请求 获取一些数据,包括图片的 URL
- 一旦数据到达,文本数据将用于填充 CoreData 模型
- 同时,调度第二个线程异步下载 图片;该线程将通过 KVO 向 viewController 发送信号 图像已缓存并在 CoreData 模型中可用。
- 由于图片下载需要一段时间,我们立即返回 CoreData 对象,它具有除图像之外的所有属性 来电者。
- 另外,当第二个线程完成下载时,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];
});
所以显然我并没有真正在屏障之前调度图像加载块,否则屏障会等到图像加载块完成后再执行(这是我的意图)。
我做错了什么?如何确保图像加载块在屏障块之前入队?
【问题讨论】:
标签: ios cocoa-touch concurrency objective-c-blocks grand-central-dispatch