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

我们在开发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刷新的效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • 我们在开发APP的时候可能都会遇到在一个页面请求多个接口的情况,如果在每个接口请求成功后都刷新UI可能会出现闪屏的...
    Fendouzhe阅读 93评论 0 2
  • NSThread 第一种:通过NSThread的对象方法 NSThread *thread = [[NSThrea...
    攻城狮GG阅读 795评论 0 3
  • 谈到iOS多线程,一般都会谈到四种方式:pthread、NSThread、GCD和NSOperation。其中,苹...
    攻城狮GG阅读 268评论 0 3
  • 2017-07-28iOS开发 导语:在iOS中,多线程方案有四种:pthread、NSThread、NSOper...
    C9090阅读 401评论 0 1
  • 今天晨读很有意思,虽然是三种现象,但很多时候都发生在同一种人身上。这种人自认为自己牛逼轰轰,自尊心很强,输不起,自...
    Janet大昕鼓徵阅读 113评论 0 0