dispatch group
有时候我们会有这种需求,在刚进去一个页面需要发送两个请求,并且某种特定操作必须在两个请求都结束(成功或失败)的时候才会执行,最low的办法第二个请求嵌套在第一个请求结果后在发送,在第二个请求结束后再执行操作。还有就是只使用一个Serial
Dispatch Queue,把想要执行的操作全部追加到这个Serial Dispatch
Queue中并在最后追加某种特定操作,颇为复杂操作。但是呢,我们这里介绍更高级的办法使用dispatch group。
我们将ABC三个任务block追加到Global Dispatch Queue,ABC全部执行完,会执行dispatch_group_notify中的block。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_creat();
dispatch_group_async(group,queue,^{执行任务A});
dispatch_group_async(group,queue,^{执行任务B});
dispatch_group_async(group,queue,^{执行任务C});
dispatch_group_notify(group,dispatch_get_main_queue(),^{执行最终的特定操作});
ABC的执行顺序不固定,因为是Global Dispatch Queue即Concurrent Dispatch Queue多个现场并行执行。
上面的dispatch_group_notify(group,dispatch_get_main_queue(),^{执行最终的特定操作});操作还可以更改为
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
dispatch_group_wait第二个参数指定为等待的时间(超时),属于dispatch_time_t类型,在这里使用DISPATCH_TIME_FOREVER,意味着永久等待。如果dispatch group的处理尚未结束,就会一直等待。
如果指定等待时间为1秒如下:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NESC_PER_SEC);
long result = dispatch_group_wait(group,time);
if(result == 0) { dispatch group的全部处理执行结束}
else { dispatch groupe的某一处理还在执行中};
但是呢上面这种dispatch_group的排列执行方式,是不会考虑block块内部的异步请求情况的,它只能保证把block内的非异步直观代码执行完,所以如果ABC三个任务中如果有执行异步的请求,那么在dispatch_group_notify最终任务执行中,那个异步请求不一定毁掉结束。
在这里给大家介绍针对这种问题另一个API。
dispatch_group_enter/dispatch_group_leave
dispatch_group_t group = disoatch_group_creat();
dispatch_group_enter(group);
dispatch_async(dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//在这里执行异步请求A
并且在执行结束代码(成功或失败)中写上dispatch_group_leave(group);
});
dispatch_async(dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//在这里执行异步请求B
并且在执行结束代码(成功或失败)中写上dispatch_group_leave(group);
});
dispatch_group_notify(group,dispatch_get_main_queue(),^{执行最终的特定操作});
上面这种做法当执行到dispatch_group_notify,一定是AB两个异步请求都加在结束了。dispatch_group_enter(group)和dispatch_group_leave(group);必须成对出现,编译器会强制识别当出现dispatch_group_leave全部结束才执行dispatch_group_notify,即使这种,档异步执行了AB两个请求,也不能保证请求执行结束的先后顺序,如果任务B的请求参数包含请求A的返回参数,那么只能用最Low的办法将请求B嵌套在A中执行,当然如果你有更好的办法欢迎提出来哈。
最近的项目正好有多个请求并发执行,但需要返回所有请求的结果之后,再更新界面的需求,正好用到dispatch group,还比较满足需求,但是碰到任务B的请求参数包含请求A的返回参数这种情况也有可能,还真是需要找一个优雅的姿势解决这种情况。
转自:http://www.cocoachina.com/ios/20160804/17291.html