6

我正在调用四个要以同步顺序执行的方法,前两个方法是同步的,后两个方法是异步的(从 URL 获取数据)。

伪代码:

- (void)syncData {

    // Show activity indicator
    [object sync]; // Synchronous method
    [object2 sync]; // Synchronous method
    BOOL object3Synced = [object3 sync]; // Async method
    BOOL object4Synced = [object4 sync]; // Async method
    // Wait for object3 and object4 has finished and then hide activity indicator
}

我怎样才能做到这一点?

4

4 回答 4

25

使用屏障:

void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);

提交一个用于异步执行的屏障块并立即返回。

当屏障块到达私有并发队列的前面时,它不会立即执行。相反,队列一直等待,直到其当前正在执行的块完成执行。此时,队列自己执行屏障块。在屏障块完成之前,在屏障块之后提交的任何块都不会执行。

此示例输出1 2 3 4 done虽然是异步的,但可能是1 2 4 3 done. 由于我了解您要处理活动指示器,因此这无关紧要。

#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
    @autoreleasepool {
        dispatch_queue_t queue = dispatch_queue_create("com.myqueue", 0);
        dispatch_sync(queue,  ^(){NSLog(@"1");} );
        dispatch_sync(queue,  ^(){NSLog(@"2");});
        dispatch_async(queue, ^(){NSLog(@"3");});
        dispatch_async(queue, ^(){NSLog(@"4");});
        dispatch_barrier_sync(queue, ^(){NSLog(@"done");});
    }
}

其他测试异步代码的方法见:https ://stackoverflow.com/a/11179523/412916

于 2012-11-30T21:28:46.957 回答
5

假设您实际上有某种方式知道异步方法何时完成,您可能想要的是:

- (void)syncData {

    // Show activity indicator
    [object sync]; // Synchronous method
    [object2 sync]; // Synchronous method

    _object3Synced = _object4Synced = NO;
    [object3 syncWithCompletionHandler:
          ^{
               _object3Synced = YES;
               [self considerHidingActivityIndicator];
          }]; // Async method
    [object4 syncWithCompletionHandler:
          ^{
               _object4Synced = YES;
               [self considerHidingActivityIndicator];
          }]; // Async method
}

- (void)considerHidingActivityIndicator
{
     if(_object3Synced && _object4Synced)
     {
         // hide activity indicator, etc
     }
}
于 2012-11-30T21:02:21.827 回答
3

您可以创建一个子类UIActivityInidicator,添加一个activityCount属性并实现这两个附加方法:

- (void)incrementActivityCount
{
    if(_activityCount == 0)
    {
        [self startAnimating];
    }
    _activityCount++;
}

- (void)decrementActivityCount
{
    _activityCount--;
    if(_activityCount <= 0)
    {
        _activityCount = 0;
        [self stopAnimating];
    }
}

现在,每当您开始使用活动计数器调用incrementActivityCount并在其完成块中(或以其他方式完成时)调用的东西时decrementActivityCount。如果你想在这些方法中做其他事情,上面只是一个简单的例子,在大多数情况下可能就足够了(特别是如果你设置了hidesWhenStopped = YES)。

于 2012-11-30T21:02:39.550 回答
0

您需要启动第一个 Async 方法并使用完成块。在第一个异步方法的完成块中,您将启动第二个异步方法。尽管这种方式使得使用异步方法变得无关紧要。

于 2012-11-30T20:55:40.227 回答