我应该如何在iOS中使用GCD dispatch_barrier_async(似乎在其他块之前而不是之后执行)

Sal*_*rtz 15 concurrency cocoa-touch grand-central-dispatch ios objective-c-blocks

我正在尝试在iOS5中同步以下代码:

  1. 一个对象有一个方法,它发出一个HTTP请求,从中获取一些数据,包括一个图像的URL
  2. 一旦数据到达,文本数据将用于填充CoreData模型
  3. 同时,调度第二个线程异步下载图像; 当图像已经缓存并在CoreData模型中可用时,此线程将通过KVO发送信号到viewController.
  4. 由于图像下载需要一段时间,我们会立即将具有所有属性的CoreData对象返回给调用者.
  5. 此外,当第二个线程完成下载时,可以保存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
        }  
    });
}
Run Code Online (Sandbox Code Playgroud)

但是,正在发生的是基于屏障的保存块总是在图像加载块之前执行.那是,

dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSError *error = nil;
            if(![managedObjectContext save:&error]) 
            {
                //  Handle error
            }  
        });
Run Code Online (Sandbox Code Playgroud)

执行前:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                 NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
                 aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
             });
Run Code Online (Sandbox Code Playgroud)

所以显然我并没有真正在屏障之前调度图像加载块,或者屏障会等到图像加载块在执行之前完成(这是我的意图).

我究竟做错了什么?如何确保图像加载块在屏障块之前排队?

tim*_*man 28

乍一看,问题可能是您要在全局并发队列上调度屏障块.您只能在自己的自定义并发队列中使用障碍块.根据dispatch_barrier_async上的GCD文档,如果将块分派给全局队列,它将表现得像普通的dispatch_async调用.

Mike Ash在GCD屏障块上有一篇很好的博客文章:http: //www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html

祝好运

Ť