iOS 解决网络请求和界面刷新顺序问题(GCD信号量实现)
来源:互联网 发布:几个c语言小游戏源码 编辑:程序博客网 时间:2024/06/13 07:08
iOS 解决网络请求和界面刷新问题(GCD信号量实现)
功能要求瞬息万变,UI界面越来越多样化…(慢慢就习惯了,手动微笑ㄒoㄒ
) …开发中经常遇到,网络请求和界面刷新的问题解决方案。。。
考虑到大多数项目中都集成AFN, 本工程使用第三方库 AFN 作为网络请求方式。主要考虑功能,具体问题具体分析 ~
RequestTest
工程使用的是 Storyboard
快速开发、搭建的项目,目的是注重实现功能,主要是使用 GCD 的信号量 dispatch_semaphore_signal
效果在控制台中打印呈现 ㄒoㄒ
1. “一个任务需要等待另外一个任务执行完成后才可以执行” 问题解决
描述:
(1)网络请求。返回一个状态。(这是一个异步处理耗时操作,优化用户体验)
(2)人机交互。用户点击一个按钮,比如登录按钮,如果有登录状态,就执行任务3,如果没有,就等待任务1网络请求数据后,再继续执行任务3。
(3)通过点击按钮,想要执行的任务。
功能分解后主要实现
任务(1) :网络请求,请求成功后,数据调整。
任务(2) :按钮点击事件
#pragma mark - - (IBAction)clickLogonButton:(id)sender { NSLog(@"执行任务2 ..."); __weak __typeof__(self) weakSelf = self; self.block = ^() { [weakSelf doSomething]; }; if (_states && [_states isEqualToString:@"Logon"]) { NSLog(@"状态正常"); self.block(); } else { NSLog(@"状态异常"); // 若计数为0则一直等待 dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER); NSLog(@"等待状态修复 ... 再次请求"); [self request]; }}
任务(3) :模拟一个执行的任务
- (void)doSomething { NSLog(@"执行任务3: states = %@", self.states);}
2. 一个页面有多个网络请求,等待所有请求完成后,刷新页面。
主要代码:
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self request1]; }) ; dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self request2]; }) ; dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self request3]; }) ; dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"刷新界面"); });
其中网络请求request
伪代码如下:
dispatch_semaphore_t sema = dispatch_semaphore_create(0); [网络请求:{ 成功:dispatch_semaphore_signal(sema); 失败:dispatch_semaphore_signal(sema); }]; dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); // 通过使用GCD中的信号量可以解决多个操作共用同一资源时, 造成主线程阻塞的问题.
3. 按照顺序执行网络请求操作,使用NSOperationQueue 依赖实现
例如:
(1)下载图片(2)给图片添加水印(3)保存图片(4)主线程刷新UI界面
主要代码:
- (void)operationBlockTest { // 处理图片的耗时操作在子线程中执行 NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOp 下载图片 thread = %@",[NSThread currentThread]); [self request:@"下载图片"]; }]; NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOp1 给图片添加水印 thread = %@",[NSThread currentThread]); [self request:@"给图片添加水印"]; }]; NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{ [NSThread sleepForTimeInterval:2.0]; NSLog(@"blockOp2 保存图片 thread = %@",[NSThread currentThread]); [self request:@" 保存图片"]; }]; // 给blockOp1添加依赖关系,使blockOp1在blcokOp执行结束后执行 [blockOp1 addDependency:blockOp];//也就是下载结束之后再给图片添加水印,然后保存图片。一种依赖关系 [blockOp2 addDependency:blockOp1]; // 创建队列(把上面要干的事情丢到队列中同时执行--有点类似GCD中的异步,并发,开启了多个线程) NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 添加到队列 [queue addOperation:blockOp]; [queue addOperation:blockOp1]; [queue addOperation:blockOp2]; // 设置队列中操作同时执行的最大数目,也就是说当前队列中呢最多由几个线程在同时执行,一般情况下允许最大的并发数2或者3 [queue setMaxConcurrentOperationCount:3]; // 队列中可以添加其他的 BlockOperation for (int i = 0; i<50; i++) { NSBlockOperation *blockOpp = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOpp i = %d thread = %@",i,[NSThread currentThread]); }]; [queue addOperation:blockOpp]; } // 刷新UI的操作依赖关系必须在主线程中执行 NSBlockOperation *blocOpMain = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOpMain 刷新UI 显示图片,thread = %@",[NSThread currentThread]); }]; // 这两个操作的依赖关系,跨队列 [blocOpMain addDependency:blockOp2]; // 主队列 [[NSOperationQueue mainQueue] addOperation:blocOpMain];}
4. 信号量实现的生产者消费者模式
GCD实现的生产者、消费者模式
#pragma mark - 生产者、消费者模式/* 信号量实现生产者、消费者模式 GCD-信号量-实现方式 */- (void)producersAndConsumersMode{ __block int product = 0; dispatch_semaphore_t sem = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //消费者队列 while (1) { if(!dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, DISPATCH_TIME_FOREVER))){ ////非 0的时候,就是成功的timeout了,这里判断就是没有timeout 成功的时候是 0 NSLog(@"消费%d产品",product); product--; }; } }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //生产者队列 while (1) { sleep(1); //wait for a while product++; NSLog(@"生产%d产品",product); dispatch_semaphore_signal(sem); } });}
最后:
Demo地址:Demo地址(点我~)
站在巨人的肩膀上造轮子,如有冒犯,请随时联系 ~
阅读全文
0 0
- iOS 解决网络请求和界面刷新顺序问题(GCD信号量实现)
- 使用GCD 信号量来实现iOS 同步网络请求
- iOS之利用GCD信号量控制并发网络请求
- iOS之利用GCD信号量控制并发网络请求
- iOS 通过添加线程依赖和信号量结合实现一个复杂界面请求多个接口时按指定顺序执行
- iOS GCD 和信号量 实现 生产者和消费者模式
- 网络请求后关于刷新界面UI的问题
- linux网络编程之System V 信号量(二):用信号量实现进程互斥示例和解决哲学家就餐问题
- linux网络编程之System V 信号量(二):用信号量实现进程互斥示例和解决哲学家就餐问题
- iOS开发用AFNetworking和MJRefresh实现网络请求和下拉刷新、上拉加载
- GCD实现单个页面多个网络请求,需要监听所有网络请求结束后刷新UI的处理
- iOS项目中的网络请求和上下拉刷新封装
- iOS GCD之dispatch_semaphore(信号量)
- iOS --- GCD 信号量控制并发 (dispatch_semaphore)
- ios-GCD信号量
- GCD-两个网络请求同步问题
- GCD-两个网络请求同步问题
- ios 网络请求问题
- Drawerlayout实现侧滑
- bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序(置换)
- http 常见状态码
- HDU6195 | 2017 ACM-ICPC 亚洲区(沈阳赛区)网络赛-B cable cable cable
- 训练数据的充分性(2):分类器的一致收敛
- iOS 解决网络请求和界面刷新顺序问题(GCD信号量实现)
- 验证码相关
- 2017.9.10 ricehub 思考记录
- SpringBoot定时任务的设置
- ActiveMQ架构设计与最佳实践
- 10、函数的扩展 为函数参数指定默认值、函数的 rest 参数、箭头函数—ES6学习笔记
- 李沐深度学习
- IntelliJ IDEA配置Tomcat
- io框架练习