看到标题,我想大部分iOS开发的童鞋能想到好几种方案。比如下一个网络请求必须依赖上一个网络请求的结果才可以进行,最简单直白的方法是:“同步调用”。这里所说的同步是指,等上一个网络请求任务完成后,直接在返回数据的delegate或者block中执行下一个网络请求。

但是,如果碰到我下面这种情况呢?

假设现在有三个任务:

任务1: 通过网络请求检测一种状态,这是一个网络耗时的操作。

任务2: 用户点击一个按钮,比如登录按钮。就会去检测有没有请求到这个状态,如果有就继续执行3,没有就等待任务1请求到所需状态后,再继续执行任务3。

任务3:想通过点击按钮,想要执行的任务,该任务不是本文讨论的重点。

可以看到,虽然说,都是属于“一个任务需要等待另外一个任务完成后才可以执行”的问题范畴,但由于代码执行流不同,所以有不能按以往方式处理。

下面给出我的解决办法:

预先设置好所需要的属性或者实例变量

@property (strong, nonatomic) dispatch_semaphore_t lock;
@property (copy, nonatomic) NSString *states;
@property (copy, nonatomic) dispatch_block_t block;

第一步,模拟一个网络请求检测状态的过程,假设耗时10s。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{sleep(10);_states = @"Logon";});

10s后,网络请求到我们所需的状态,比如是一个字符串“Logon”。

第二步,模拟用户点击登录按钮时,所需状态存在的情况下,要去执行的任务3。

- (IBAction)clickLogonButton {if (_states && [_states isEqualToString:@"Logon"]) {[self doSomething];}
}

好了,按照现有的代码逻辑看,我们在点击登录按钮后,先检测所需的状态是不是存在,如果存在,就继续执行任务3,此处指 - doSomething。这个方法比较简单,我们就仅仅打印一下此时的状态。

- (void)doSomething {NSLog(@"states = %@", self.states);
}

假设在界面出现时,我们去网络请求状态。

- (void)viewDidAppear:(BOOL)animated {[super viewDidAppear:animated];[self checkStates];
}

运行程序,当界面出现的时候,我们点击登录按钮,没有打印任何日志。因为此时,我们的请求还没有拿到所需状态,自然执行不了任务3:- doSomething,这个比较好理解。

我们的需求是,如果状态没有请求到,就让程序暂时”挂起“,等拿到所需状态,再去执行任务3。

我的解决办法是使用信号量,让两个任务执行方式从异步转成同步执行,上代码:

- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.lock = dispatch_semaphore_create(1);
}
- (IBAction)clickLogonButton {if (_states && [_states isEqualToString:@"Logon"]) {[self doSomething];} else {dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);}
}
- (void)checkStates {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{sleep(10);_states = @"Logon";dispatch_semaphore_signal(self.lock);[self clickLogonButton];});
}

运行程序,不管什么时候,点击登录按钮,我们都可以执行到任务3:- doSomething。

但是有个问题,我们在得到状态后,是重新执行了一遍登录事件,这样明显是不合理的。因为我们要从等待状态后的代码执行起,而不是重新来一遍,在本文的例子中可能影响没有那么明显,但在复杂的的项目中,这样做是绝对不靠谱的。简单说,我要告诉程序,已经成功获取到了状态,你可以继续往下执行了,也就是回调。那怎么告诉呢?我们想到block,这也是为什么在本文开头我声明了一个block属性。代码修改如下:

- (IBAction)clickLogonButton {NSLog(@"执行任务2 ...");__weak __typeof__(self) weakSelf = self;self.block = ^() {[weakSelf doSomething];};if (_states && [_states isEqualToString:@"Logon"]) {NSLog(@"状态正常");self.block();} else {NSLog(@"状态异常");dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);NSLog(@"等待状态修复 ...");}
}- (void)doSomething {NSLog(@"执行任务3: states = %@", self.states);
}
- (void)checkStates {NSLog(@"准备执行任务 1");dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{NSLog(@"任务1 正在执行中 ...");sleep(10);_states = @"Logon";dispatch_semaphore_signal(self.lock);NSLog(@"任务1 执行完成");if (self.block) {self.block();}});
}

目前程序按预期完美运行,如果有更好的方案或者问题,我们可以共同探讨。

iOS 如何巧妙解决“一个任务需要等待另外一个任务完成后才可以执行”的问题相关推荐

  1. ajax调用上一个ajax,关于jquery:当频繁使用ajax请求调用函数时,如何在处理下一个请求之前等待上一个ajax请求完成?...

    本问题已经有最佳答案,请猛点这里访问. 我在我的代码中有一个ajax请求,如下所示: function show_detail() { $('#product_'+index).html(' load ...

  2. selenium之显示等待(等到某个元素出现后再继续执行)

    本文章还请认真仔细阅读,非常简单,阅读前,你可能已经掌握,xpath 我们在爬虫的时候,总会利用time.sleep(),去等待元素的出现,但是这很容易出错,因为你不知道你的网速有多卡

  3. 巧妙解决window系统盘不足 而又不想全盘格式分区 增加C盘空间大小的问题

                     巧妙解决window系统盘不足 而又不想全盘格式分区 增加C盘空间大小的问题   默认情况下 往往C盘设置30G左右 刚开始以为够用 尤其是比较久的电脑和笔记本 硬盘 ...

  4. iOS 11开发教程(二)编写第一个iOS 11应用

    iOS 11开发教程(二)编写第一个iOS 11应用 编写第一个iOS 11应用 本节将以一个iOS 11应用程序为例,为开发者讲解如何使用Xcode 9.0去创建项目,以及iOS模拟器的一些功能.编 ...

  5. 运行时错误76未找到路径怎么解决_自动化测试解决竞争问题?等待一下就行了~...

    由于WebDriver和浏览器分别运行在自己的进程中,所以WebDriver无法实时追踪到浏览器中页面DOM树的渲染情况,也就是在WebDriver的执行和浏览器的渲染间存在一个竞争问题(race c ...

  6. iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

    iOS开发UI篇-使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 iOS开发UI篇-使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目 ...

  7. iOS开发中解决第三方静态库符号冲突的终极方案

    iOS开发中解决第三方静态库符号冲突的终极方案 背景 在iOS开发的时候,经常会使用各种第三方静态库,这些库内部可能会打包了相同的第三方库.那么在链接的时候就会发生符号冲突. 例如:A厂商提供的lib ...

  8. idea 报系统分区磁盘不足_磁盘空间不足—win7系统磁盘空间不足巧妙解决

    很多朋友经常使用电脑的时候会遇到磁盘空间不足的问题,这就意味着该磁盘空间已容纳不下您所需存放的资料.在不知情下,使用迅雷下载.U盘拷贝到空间不足的系统磁盘中,均会提示关于当前磁盘空间不足的问题. 现如 ...

  9. 微信小程序设置swiper圆角在ios上失效解决

    今天在给轮播图添加圆角的时候,发现在安卓机上是有圆角的,但是在苹果手机上圆角却失效了,后来翻阅了文档发现这是个bug.下面是两种解决方案:第一种:-webkit-backface-visibility ...

最新文章

  1. 关于css的float
  2. Android ProGuard使用要点!
  3. retinaface人脸对齐
  4. python数组用sum求和_对python中array.sum(axis=?)的用法介绍
  5. Qt Creator代码重构
  6. 2016年10月计算机网络技术,2016年10月自考《计算机网络技术》练习题及答案1
  7. 信息学奥赛一本通 1172:求10000以内n的阶乘 | OpenJudge NOI 1.6 14:求10000以内n的阶乘
  8. Owner PID: 7948 Our PID: 7064
  9. Python模拟汉诺塔问题移动盘子的过程
  10. Python 常用函数Logging
  11. mysql卸载详细教程
  12. 设计Instagram
  13. Firefox浏览器购物比价插件:惠惠购物助手
  14. SpringBoot Validation参数校验 详解自定义注解规则和分组校验
  15. R 语言图形函数 par()参数应用举例
  16. 如何用matlab求解多变量非线性回归,matlab多元非线性回归教程
  17. Linux网卡流量限制
  18. T32 simulator
  19. 华三模拟器:实现路由器接口使用dhcp获取地址
  20. python爬取boss直招_简易python爬虫爬取boss直聘职位,并写入excel

热门文章

  1. pandas 批量读取excel_怎样使用Pandas批量拆分与合并Excel文件?
  2. 电信联通iphone5前夜打响用户争夺战
  3. mysql查询 展示横纵坐标_sql 分组统计查询并横纵坐标转换
  4. css设置p标签多余文字显示省略号
  5. 二进制在数学中的妙用(转帖)
  6. QT给控件绑定数据:setProperty
  7. Duplicated jQuery selector
  8. 计算机专业技术能力证明材料,专业技术能力承诺书
  9. 全球与中国伊维菌素药物市场深度研究分析报告
  10. 4g信号满2g无服务器,为什么手机信号变成2g?为什么手机4G信号突然变成2G信号了?...