dispatch_group实践,AFN3.0多个网络请求
2017-08-25 01:42
239 查看
dispatch_group实践,AFN3.0多个网络请求
在实际开发过程中经常会有在一个页面有多个网络请求,页面UI需要在所有网络请求全部回来的情况下更新。先简单看一个具体的问题:页面有三个网络请求a、b、c。三个网络请求都成功的情况下刷新UI,有一个失败就认为请求失败,不进行UI刷新。
目前想到的方法
添加
标识进行判断是否所有的网络请求都是成功的
通过
信号量判断
直接使用
dispatch_group(当然也可以结合
信号量)
这里就简单使用
dispatch_group来实践一下:
先简单了解一下必须的东西
常用方法
1、dispatch_group_create创建一个调度任务组
2、
dispatch_group_async把一个任务异步提交到任务组里
3、
dispatch_group_enter/dispatch_group_leave这种方式用在不使用dispatch_group_async来提交任务,且必须配合使用
4、
dispatch_group_notify用来监听任务组事件的执行完毕
5、
dispatch_group_wait设置等待时间
实现一个dispatch_group_async
简单的例子
基本需求和文章前面的需求差不多,task 1、
task 2、
task 3、
task 4四个任务,
task 4要在
task 1、
task 2、
task 3执行完成之后在执行。
先看一下代码:
- (void)testDisGroup { dispatch_queue_t demoQuene = dispatch_queue_create("demoQuene", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group = dispatch_group_create(); NSLog(@"\n\nmain thread %@\n\n",[NSThread currentThread]); dispatch_group_async(group, demoQuene, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 1 %@",[NSThread currentThread]); }); dispatch_group_async(group, demoQuene, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 2 %@",[NSThread currentThread]); }); dispatch_group_async(group, demoQuene, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 3 %@",[NSThread currentThread]); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"task 4 %@",[NSThread currentThread]); }); }
看一下结果:
当然
task 1、
task 2、
task 3完成的顺序不是固定,最后是
task 4,需要看系统怎么分配资源。
升级一下dispatch_group_async
的例子
在上面任务的基础上添加一个需求,就是task 2、
task 3要有一个顺序,比如
task 2要在
task 3执行完成之后才能执行。
看一下代码(当然实现的方案很多,这只是个例子):
- (void)testDisGroup { dispatch_queue_t demoQueneCONCURRENT = dispatch_queue_create("demoQuene", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t demoQueneSERIAL = dispatch_queue_create("demoQuene", DISPATCH_QUEUE_SERIAL); dispatch_group_t group = dispatch_group_create(); NSLog(@"\n\nmain thread %@\n\n",[NSThread currentThread]); dispatch_group_async(group, demoQueneCONCURRENT, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 1 %@",[NSThread currentThread]); }); dispatch_group_async(group, demoQueneSERIAL, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 3 %@",[NSThread currentThread]); }); dispatch_group_async(group, demoQueneSERIAL, ^{ sleep(arc4random_uniform(5)); NSLog(@"task 2 %@",[NSThread currentThread]); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"task 4 %@",[NSThread currentThread]); }); }
执行结果:
另一个结果:
当然这个结果也存在多种情况,不变的是
task 4要在
task 1、
task 2、
task 3执行完成之后在执行,
task 2要在
task 3执行完成之后才能执行。其他的顺序是不确定的。
使用dispatch_group_enter/dispatch_group_leave
复写一下第一个例子
-(void)testDisGroupEnterAndLeave { dispatch_queue_t demoQueneCONCURRENT = dispatch_queue_create("demoQuene2", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group = dispatch_group_create(); dispatch_group_enter(group); dispatch_async(demoQueneCONCURRENT, ^{ NSLog(@"task 1 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(demoQueneCONCURRENT, ^{ NSLog(@"task 2 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(demoQueneCONCURRENT, ^{ NSLog(@"task 3 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"task 4 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); }); }
运行结果:
另一结果:
使用dispatch_group_enter/dispatch_group_leave
复写一下第二个例子
上代码:-(void)testDisGroupEnterAndLeave { dispatch_queue_t demoQueneCONCURRENT = dispatch_queue_create("demoQuene2", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t demoQueneSERIAL = dispatch_queue_create("demoQuene3", DISPATCH_QUEUE_SERIAL); dispatch_group_t group = dispatch_group_create(); dispatch_group_enter(group); dispatch_async(demoQueneCONCURRENT, ^{ NSLog(@"task 1 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(demoQueneSERIAL, ^{ NSLog(@"task 3 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(demoQueneSERIAL, ^{ NSLog(@"task 2 %@",[NSThread currentThread]); sleep(arc4random_uniform(5)); dispatch_group_leave(group); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"task 4 %@ \n\n\n.",[NSThread currentThread]); sleep(arc4random_uniform(5)); }); }
结果(两次结果写在一起了):
开始实战
还是文章开始的那道题现在看一下页面有三个网络请求a、b、c。三个网络请求都成功的情况下刷新UI,有一个失败就认为请求失败,不进行UI刷新。
@interface TestThread () { dispatch_group_t _group; } @end @implementation TestThread - (void)p_loadBannerData { dispatch_group_enter(_group); AdvBannerApi *bannerApi = [[AdvBannerApi alloc] initWithAdvType:AdvTypeBanner]; [bannerApi startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 1 success"); dispatch_group_leave(_group); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 1 failure"); dispatch_group_leave(_group); }]; } - (void)p_loadCourseListData { dispatch_group_enter(_group); QualityCourseApi *courseApi = [[QualityCourseApi alloc] initWithStart:@"0" count:@"20"]; [courseApi startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 2 success"); dispatch_group_leave(_group); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 2 failure"); dispatch_group_leave(_group); }]; } - (void)p_loadLivingLessonData { dispatch_group_enter(_group); LessonForecastApi *api = [[LessonForecastApi alloc] init]; [api startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 3 success"); dispatch_group_leave(_group); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 3 failure"); dispatch_group_leave(_group); }]; } - (void)reloadUI { NSLog(@"task 4"); } -(void)disGroupEnterAndLeave { _group = dispatch_group_create(); [self p_loadBannerData]; [self p_loadCourseListData]; [self p_loadLivingLessonData]; dispatch_group_notify(_group, dispatch_get_main_queue(), ^{ NSLog(@"run task 4 %@",[NSThread currentThread]); [self reloadUI]; }); } @end
看一下结果:
其他的写法就一一实现了。现在看一下错误的写法
@interface TestThread () { dispatch_group_t _group; } @end @implementation TestThread - (void)p_loadBannerData { AdvBannerApi *bannerApi = [[AdvBannerApi alloc] initWithAdvType:AdvTypeBanner]; [bannerApi startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 1 success"); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 1 failure"); }]; } - (void)p_loadCourseListData { QualityCourseApi *courseApi = [[QualityCourseApi alloc] initWithStart:@"0" count:@"20"]; [courseApi startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 2 success"); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 2 failure"); }]; } - (void)p_loadLivingLessonData { LessonForecastApi *api = [[LessonForecastApi alloc] init]; [api startWithSuccessBlock:^(ApiResult * _Nullable result) { NSLog(@"task 3 success"); } failureBlock:^(NSError * _Nullable error) { NSLog(@"task 3 failure"); }]; } - (void)reloadUI { NSLog(@"task 4"); } -(void)disGroup { dispatch_queue_t demoQueneCONCURRENT = dispatch_queue_create("demoQuene", DISPATCH_QUEUE_CONCURRENT); _group = dispatch_group_create(); dispatch_group_async(_group, demoQueneCONCURRENT, ^{ [self p_loadBannerData]; }); dispatch_group_async(_group, demoQueneCONCURRENT, ^{ [self p_loadCourseListData]; }); dispatch_group_async(_group, demoQueneCONCURRENT, ^{ [self p_loadLivingLessonData]; }); dispatch_group_notify(_group, dispatch_get_main_queue(), ^{ NSLog(@"run task 4 %@",[NSThread currentThread]); [self reloadUI]; }); } @end
看一下结果:
很显然结果是错误的,
task 4最先得出了结果,主要因为
dispatch_group_async(_group, demoQueneCONCURRENT, ^{ });
开启了一个新线程,然后
[self p_loadBannerData];
网络请求又开启了一个线程。
dispatch_group_async(_group, demoQueneCONCURRENT, ^{ });
开启的3个新线程执行完之后执行
task 4。网络耗时的操作才执行。然后就………………错了。
相关文章推荐
- Swift-利用AFN封装网络请求
- iOS AFN监听网络,封装网络请求 —— HERO博客
- iOS之网络请求及各类错误代码含义总结(包含AFN错误码大全)
- iOS重构——轻量级的网络请求封装实践
- 使用AFN 进行多次循环网络请求,如何判断何时请求完成
- Android网络请求发展简史和RxJava+Retrofit+OkHttp实践
- AFN三方文件 监测网络状态 请求网络数据
- ReactiveCocoa代码实践之-RAC网络请求重构
- (iOS-框架封装)AFN3.x 网络请求封装
- ExpandableListView 实现点击某个group的时候再去请求网络动态加载子视图中的数据
- iOS-网络请求-AFN升级至AFN3.0
- 网络请求及各类错误代码含义总结(包含AFN错误码大全)
- iOS AFN 封装POST网络请求(AFURLSessionManager)
- 网络请求之基于AFN的二次封装从AFN1.0升级到3.0后)
- 源码推荐(01.14B):AFN网络请求一句代码搞定,iOS 9最新的UIAlertController
- AFN网络请求封装(MRC模式, 若是ARC模式 需添加 -fno-objc-arc )
- 【iOS】AFN网络请求通过获取cookies保持会话
- iOS开发总结之block回调以AFN为基础封装的网络请求操作类
- 基于AFN封装的带缓存的网络请求
- iOS之网络请求之AFN表单上传之form-data