Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 等待许多异步调用以执行回调_Ios_Objective C_Ios5_Block - Fatal编程技术网

Ios 等待许多异步调用以执行回调

Ios 等待许多异步调用以执行回调,ios,objective-c,ios5,block,Ios,Objective C,Ios5,Block,我想用web服务同步一些数据。对于每个项目,我必须进行异步调用 我想在同步每个项目时调用一个完成块。对于每一项,我都能执行一个完成块。现在,我不知道怎么做才好 这是接口: -(void) synchronizeItemsOnComplete:(CompleteBlock) block { NSArray* items = // get items for (int i = 0, n = [items count]; i < n; i++) { [self sy

我想用web服务同步一些数据。对于每个项目,我必须进行异步调用

我想在同步每个项目时调用一个完成块。对于每一项,我都能执行一个完成块。现在,我不知道怎么做才好

这是接口:

-(void) synchronizeItemsOnComplete:(CompleteBlock) block {
    NSArray* items = // get items
    for (int i = 0, n = [items count]; i < n; i++) {
       [self synchronizeItem:[items objectAtIndex:i] onComplete:^{
          // What do do here?
       }];
    }
    // And/or here?
}

-(void) synchronizeItemOnComplete:(CompleteBlock) block {
    // do something
    block();
}
-(void)synchronizeItemsOnComplete:(CompleteBlock)块{
NSArray*items=//获取项目
对于(int i=0,n=[项目计数];i
如何等待同步,然后执行块

我试过这样的方法:

NSArray* items = // get items

__block int countOfItemsUntilDone = [items count];

for (int i = 0, n = countOfItemsUntilDone; i < n; i++) {
    [self synchronizeItem:[items objectAtIndex:i] onComplete:^{
        countOfItemsUntilDone--;
    }];
}

dispatch_queue_t queue = dispatch_queue_create("wait for syncing", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    while (countOfItemsUntilDone > 0) {
        usleep(1000); // wait a little bit
    }
    block();
});
dispatch_release(queue);
NSArray*items=//获取项目
__block int countOfItemsUntilDone=[items count];
for(int i=0,n=countOfItemsUntilDone;i0){
usleep(1000);//稍等
}
block();
});
调度释放(队列);

但我认为这是一个相当糟糕的方式。有什么想法吗?

您可以使用这些想法同步使用


性能选择器:waitUntilDone:YES

不是在循环中旋转等待计数器等于零,而是在每次减小计数器值时检查它,然后在它达到零时触发事件

 -(void) synchronizeItemsOnComplete:(CompleteBlock) block {
    NSArray* items = // get items
    __block NSUInteger remaining = [items count];

    for (ItemClass* item in items) {
       [self synchronizeItemImage:item onComplete:^{
            --remaining;
            if (remaining == 0) {
                block();
            }
       }];
    }
 }
为了解释为什么感觉不对,这里有两件事你应该永远不要做或很少做:

  • 使用后台队列。这很困难,而且容易出现错误。如果没有阅读大量关于编写并发代码的内容,就不要这样做。如果操作阻塞了相当长的时间(例如,从磁盘读取文件,或执行密集计算),您也确实需要这样做。除非你有充分的理由(例如,可测量的性能问题),否则不要认为你需要这样做

  • 在循环中旋转,检查变量的变化并调用sleep。你不应该这样做


另外,如果在数组中的元素上循环,则。。。在
中,在每个索引上调用objectAtIndex:的语法更好(而且可能更有效)。

不要像这样检查或减少不同线程中的共享内存,这可能会导致争用。使用调度组执行您正在执行的操作

dispatch_queue_t myBGQueue;
dispatch_group_t itemsGroup = dispatch_group_create();

for (ItemClass *item in items) {
    dispatch_group_async(itemsGroup, myBGQueue, ^{
        [self synchronizeItemImage:item];
    });
}

/* execution will sleep here until all the blocks added in the `for` complete */
dispatch_group_wait(itemsGroup, DISPATCH_TIME_FOREVER);

dispatch_release(itemsGroup);

哦我没有说清楚那一点。那个叫做synchronizeItemImage的方法通过RESTKit启动一个异步请求。因此,异步或使用
waitUntilDone:
执行该方法可能不起作用。为了避免减少不同线程中的共享内存,我可以在串行调度队列上执行Chris Devereux解决方案中的块,或者这也很糟糕?哦。在这种情况下,只要在主线程上调用完成处理程序,就可以减少一些变量。或者更好的方法是,减少windowController或应用程序委托上的属性,并使用KVO通知来确定它何时达到零。