【问题标题】:enumerateObjectsUsingBlock and completion togetherenumerateObjectsUsingBlock 和完成一起
【发布时间】:2016-06-28 08:02:52
【问题描述】:

我有一种情况,我正在使用 enumerateObjectsUsingBlock 迭代我的数组对象,我需要等待迭代完成然后它应该执行进一步的代码,我该如何实现这一点,或者如果我应该使用任何替代方案,下面是我的代码

[arrPendingQueue enumerateObjectsUsingBlock:^(PendingQueues *obj, NSUInteger idx, BOOL *stop) {

       //Fetch static google map based on coordinates
       [self generateMapImage:obj.postObj completion:^(UIImage *image) {
           NSString *path = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"camera"];

          NSString *resultPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"map_%f.jpg",[[Constants getSystemDateInLocalTimeZone] timeIntervalSince1970]]];

          [[NSFileManager defaultManager] createFileAtPath:resultPath contents:UIImageJPEGRepresentation(image, 1.0) attributes:nil];

          postObj.imagepath = [@"camera" stringByAppendingPathComponent:[resultPath lastPathComponent]];

          [DataManager saveObject:postObj];                                             
       }];

       //After the completion I want to upload the data here to server

});

基本上,我正在尝试从函数generateMapImage 中的坐标下载静态谷歌地图,我希望循环等到调用完成..

为此,我尝试使用 dispatch_semaphore_create 之类的

[arrPendingQueue enumerateObjectsUsingBlock:^(PendingQueues *obj, NSUInteger idx, BOOL *stop) {
     dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

     [self generateMapImage:obj.postObj completion:^(UIImage *image) {

         dispatch_semaphore_signal(semaphore);                                    
     }];

     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

});

但它不工作它不等待,并在完成之前执行代码。

如何解决,请帮忙。

谢谢。

【问题讨论】:

  • 使用自定义NSOperation子类
  • 是等待每一步的单个操作完成还是等待所有操作完成?
  • @AminNegm-Awad 完成每个步骤中的单个操作。
  • @SahebRoy NSOperation 有什么帮助,可以给它更多的亮点,它仍然需要等待执行..
  • 嗯,应该与信号量一起使用。你确定实际操作没有完成吗?但是,为什么不将等待的代码移到完成块中呢?

标签: ios objective-c completionhandler


【解决方案1】:

要排队执行一系列块,您可以简单地在旧块的完成处理程序中启动新块:

NSEnumerator *objectEnum = [arrPendingQueue objectEnumerator];
__block void (^handler) ();
handler = ^(UIImage *image)
{
   // Handle image
   object = [objectEnum nextObject];
   if( object == nil )
   {
     // completion of all operations
   }
   else 
   {
     // Start next operation
     [self generateMapImage:object.postObj completion:handler];
   }                                    
 };
 [self generateMapImage:obj.postObj completion:handler];
}

更经典或更优雅的方式是使用Y-combinator。但这不是必需的。请记住,局部范围变量在失去范围时会被清除。 handler 不保留。所以也许你必须把它放到一个 ivar 中。

但是,我看到-generateMapImage:completion 是你写的。我看不到内容,但是如果您在那里进行异步调用并且可以设置用于调用的队列,只需将其设置为串行队列即可。在这种情况下,您的请求将自动串行执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 2014-08-04
    • 1970-01-01
    • 2021-02-09
    相关资源
    最近更新 更多