我正在调用我想以同步顺序执行的四个方法,前两个方法是同步的,后两个方法是异步的(从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
}
我怎样才能做到这一点?
答案 0 :(得分:25)
使用屏障:
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
提交一个用于异步执行的屏障块并立即返回。
当障碍块到达私有并发的前面时 队列,它不会立即执行。 相反,队列等待,直到当前正在执行的块完成执行。 那时, queue自己执行barrier块。之后提交的任何块 在屏障块完成之前,不会执行屏障块。
此示例输出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
答案 1 :(得分: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
}
}
答案 2 :(得分: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
)。
答案 3 :(得分:0)
您需要启动第一个Async方法并使用完成块。在第一个异步方法的完成块中,您将启动第二个异步方法。虽然这种方式使得使用异步方法无关紧要。