最近做到一个页面里有四个接口,每一个接口返回都有对应的 UI 改变,所以要四个接口全部请求返回成功后,再去做 UI 刷新。然而由于网络请求用的是 AFN 等第三方库,本身就是异步的,所以 GCD 的栅栏函数
是没有用的。
- dispatch_barrier_async
那么就让他一个一个的执行,等到所有都执行完成后再去刷新 UI,于是乎呢,可以在第一个网络请求了的返回 block 里去做第二个网络请求,以此类推就可以完成最后的 UI 刷新。这个不失为一种比较有效的方法,但是这样写的代码真的挺丑的。。。。
如果单纯的想让这几个网络请求按顺序执行,先进先出,那就是队列啊,iOS 里提供的队列管理就是 GCD 这个强大的 c 语言实现的库。GCD 里面有一个信号量 --dispatch_semaphore_t,
创建一个信号量,如果 value 小于 0 的话,这个信号量就是 nil。
- dispatch_semaphore_create(long value);
可以让信号量减 1,如果信号量是 0,那么他会等待信号量为非零才会执行下一步。
- dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
可以让信号量增加 1.
- dispatch_semaphore_signal(dispatch_semaphore_t dsema);
通过这上面的方法,我们可以一开始设计信号量是 0,每一个网络请求之前用
, 请求结束回调里用
- dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
这样可以让请求按照顺序执行下来。Talk is cheep,show your the code:
- dispatch_semaphore_signal(dispatch_semaphore_t dsema);
- - (void) semaphoretest {
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- sleep(2);
- NSLog(@"任务1完成---- %@", [NSThread currentThread]);
- dispatch_semaphore_signal(semaphore);
- });
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- sleep(2);
- NSLog(@"任务2完成---- %@", [NSThread currentThread]);
- dispatch_semaphore_signal(semaphore);
- });
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- sleep(2);
- NSLog(@"任务3完成---- %@", [NSThread currentThread]);
- dispatch_semaphore_signal(semaphore);
- });
- }
打印结果如下:
很清楚的看到了他们是按照顺序执行的。
最好的设计当然是他们几个并发执行,到时候全部请求结束后再去做 UI 的刷新。于是乎想到了 CGD 的 group 啦!GCD 就是辣么强大有木有!设计如下:
- - (void) groupTest {
- dispatch_queue_t quete = dispatch_queue_create("XIAXIAQUEUE", DISPATCH_QUEUE_CONCURRENT);
- dispatch_group_t group = dispatch_group_create();
- dispatch_group_enter(group);
- dispatch_group_async(group, quete, ^{
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- sleep(5);
- NSLog(@"网络任务1完----%@", [NSThread currentThread]);
- dispatch_group_leave(group);
- });
- sleep(2);
- NSLog(@"任务1完成---%@", [NSThread currentThread]);
- });
- // dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- dispatch_group_enter(group);
- dispatch_group_async(group, quete, ^{
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- sleep(5);
- NSLog(@"网络任务2完成----%@", [NSThread currentThread]);
- dispatch_group_leave(group);
- });
- sleep(2);
- NSLog(@"任务2完成---%@", [NSThread currentThread]);
- });
- // dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- dispatch_group_enter(group);
- dispatch_group_async(group, quete, ^{
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- sleep(5);
- NSLog(@"网络任务3完成 --- %@", [NSThread currentThread]);
- dispatch_group_leave(group);
- });
- sleep(2);
- NSLog(@"任务3完成---- %@", [NSThread currentThread]);
- });
- dispatch_group_notify(group, dispatch_get_main_queue(), ^{
- NSLog(@"最后执行 ---- %@", [NSThread currentThread]);
- });
- }
打印的结果如下:
首先可以发现其实这几个任务都是在不同的线程的,但是最后执行的肯定是最后一步!
作为一个程序猿,思考是最重要的,虽然现在网上很多代码可以用拿来主义,但是如果只会拿来,那只能作为一个初级的程序猿了。所以有时候多思考,多想想。
来源: https://juejin.im/post/5a4344eef265da430e4f6fd1