美文网首页
GCD实现多个异步线程同步刷新UI

GCD实现多个异步线程同步刷新UI

作者: Fendouzhe | 来源:发表于2017-12-12 17:14 被阅读0次

我们在开发APP的时候可能都会遇到在一个页面请求多个接口的情况,如果在每个接口请求成功后都刷新UI可能会出现闪屏的情况,也可能出现由于数据源不完整导致刷新UI时程序崩溃。那么该如何保证这多个请求之间异步执行且只有在所有请求都成功返回后再进行UI刷新呢?在网上搜索了很多例子基本都是用dispatch_group_asyncdispatch_group_tdispatch_group_notify 组合来实现的。这种方式只是做对了一半,其实现如下:

dispatch_group_t  group = dispatch_group_create();
dispatch_queue_t  queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
        NSLog(@"1");
    });
dispatch_group_async(group, queue, ^{
        NSLog(@"2");
    });
dispatch_group_async(group, queue, ^{
       NSLog(@"3");
    });
 dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"4");
    });

程序运行之后1、2、3先异步执行,然后1、2、3都返回后 4 再最后执行。到这里看似满足了 所有请求都返回后再刷新UI 的要求,但是当我按照这个思路来实现多个网络请求时,发现1、2、3、4的顺序却完全打乱了,4并不总是在最后执行。经过多次调试后才发现原因是因为上面每一个NSLog(...)本身都是同步执行的,而我想要的网路请求本身却是个异步操作。如下

dispatch_group_async(group, queue, ^{
       [[SFAPIManager sharedManager] requestDataWithPath:urlPath params:@{@"id":@"1"} completeBlock:^(id result, NSError *error) {
        NSLog(@"-------%@",result);
       }];
 });

这会导致在网络请求未回来之前block就已经提前返回了,所以以上代码实现是错误的。正确的方法应该是以上三个函数再配合dispatch_group_enter(group)dispatch_group_leave(group)两个函数一起来使用,这样才能实现我们想要的最终效果。

dispatch_group_enter(dispatch_group_t group);
参数group不能为空,在异步任务开始前调用。它明确的表明了一个 block 被加入到了队列组group中,此时group中的任务的引用计数会加1(类似于OC的内存管理),dispatch_group_enter(group)必须与dispatch_group_leave(group)配对使用,它们可以在使用dispatch_group_async时帮助你合理的管理队列组中任务的引用计数的增加与减少。

dispatch_group_leave(dispatch_group_t group);
参数group不能为空,在异步任务成功返回后调用。它明确的表明了队列组里的一个 block 已经执行完成,队列组中的任务的引用计数会减1,它必须与dispatch_group_enter(group)配对使用,dispatch_group_leave(group)的调用次数不能多于dispatch_group_enter(group)的调用次数。

当队列组里的任务的引用计数等于0时,会调用dispatch_group_notify函数。具体代码实现如下:

@property (nonatomic,strong) dispatch_group_t disGroup;

- (void)requestDatas {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(self.disGroup);
    dispatch_group_enter(self.disGroup);
    dispatch_group_enter(self.disGroup);
    
    dispatch_group_async(self.disGroup, queue, ^{
        [self requestHomeWorks];
    });
    
    dispatch_group_async(self.disGroup, queue, ^{
        [self requestHomeBanner];
    });
    
    dispatch_group_async(self.disGroup, queue, ^{
        [self requestHomeAdvInfos];
    });
       
    dispatch_group_notify(self.disGroup, dispatch_get_main_queue(), ^{
        NSLog(@"4");
        [self.collectionView reloadData];
    });
}
- (void)requestHomeWorks {
    [[SFAPIManager sharedManager] requestDataWithPath:kHomeWorksPath params:nil completeBlock:^(id result, NSError *error) {
        NSLog(@"1");
        dispatch_group_leave(self.disGroup);
    }];
}
- (void) requestHomeBanner {
    [[SFAPIManager sharedManager] requestDataWithPath:kHomeBannerPath params:nil completeBlock:^(id result, NSError *error) {
        NSLog(@"2");
        dispatch_group_leave(self.disGroup);
    }];
}
- (void) requestHomeAdvInfos {
    [[SFAPIManager sharedManager] requestDataWithPath:kHomeAdvInfosPath params:nil completeBlock:^(id result, NSError *error) {
        NSLog(@"3");
        dispatch_group_leave(self.disGroup);
    }];
}

这样就可以实现多个网络请求之间异步执行,且只有在所有请求都返回后才会执行UI刷新的效果。

相关文章

  • GCD实现多个异步线程同步刷新UI

    我们在开发APP的时候可能都会遇到在一个页面请求多个接口的情况,如果在每个接口请求成功后都刷新UI可能会出现闪屏的...

  • GCD实现多个异步线程同步刷新UI

    我们在开发APP的时候可能都会遇到在一个页面请求多个接口的情况,如果在每个接口请求成功后都刷新UI可能会出现闪屏的...

  • GCD 相关函数

    串行同步 串行异步 并行同步 并行异步 主队列同步 会死锁 主队列异步 异步处理耗时,回主线程刷新UI 栅栏函数 ...

  • 多线程相关面试问题

    多线程:GCD、NSOperation、NSThread。 一、GCD 1、同步/异步 和 串行/并发(1)、同步...

  • GCD中的串行,并行,同步,异步详解

    gcd中的串行,并行,同步,异步详解 1、gcd中同步与异步的区别: gcd中的线程是由一个线程池来管理的,这个池...

  • iOS面试之多线程模块

    多线程 多线程内容如下: GCD NSOperation NSThread 多线程与锁 1.GCD 同步/异步和串...

  • 多线程之GCD

    GCD术语 串行和并行 同步和异步 关键段 竞争条件 死锁 线程安全 线程上下文切换 平行与并发 平行:多个线程可...

  • OC 线程笔记

    GCD: 创建任务,添加到队列,GCD自动分发任务 同步/异步同步任务,异步任务的区别: 线程是否要等待任务结束,...

  • iOS面试 -- 多线程相关

    多线程技术方案 GCD NSOperation NSThread GCD 同步/异步 和串行/并发 dispatc...

  • 多线程

    GCD NSOperation NSThread 多线程与锁 一、GCD 同步、异步 和 串行、并发 dispat...

网友评论

      本文标题:GCD实现多个异步线程同步刷新UI

      本文链接:https://www.haomeiwen.com/subject/kounixtx.html