iOS 依次执行 异步网络请求的一种实现

来源:互联网 发布:pptv聚力网络电视2017 编辑:程序博客网 时间:2024/05/24 06:57

1.首先先介绍一个概念dispatch_semaphore


  • dispatch_semaphore信号量为基于计数器的一种多线程同步机制。用于解决在多个线程访问共有资源时候,会因为多线程的特性而引发数据出错的问题.
  • 如果semaphore计数大于等于1,计数-1,返回,程序继续运行。如果计数为0,则等待。
  • dispatch_semaphore_signal(semaphore)为计数+1操作。dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)为设置等待时间,这里设置的等待时间是一直等待。我们可以通俗的理解为单柜台排队点餐,计数默认为0,每当有顾客点餐,计数+1,点餐结束-1归零继续等待下一位顾客。比较类似于NSLock。

2.主要是介绍使用dispatch_semaphore和NSOperationQueue结合实现依次执行异步请求


  • NSOperationQueue中装有任务,设置任务之间相互依赖
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{     [self request:@”A”]; }];NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{    [self request:@"B"];}];NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{     [self request:@”C”]; }];[operation2 addDependency:operation1]; //任务二依赖任务一 [operation3 addDependency:operation2]; //任务三依赖任务二
  • 将任务加入队列中
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO]; 
  • 测试执行顺序并非是按照A-B-C依赖执行,并且无法得知何时任务执行完毕,进行下一步操作.下面解决这两个问题

3.解决如何依次执行.就要用到开头介绍的:dispatch_semaphore来限制是否执行

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //默认创建的信号为0[[NetworkManager shared] RequestWithMethod:HttpMethod_POST Url:strURL params:params success:^(NSURLSessionDataTask *task, id responseObject) {    NSLog(@"%@",index);    dispatch_semaphore_signal(semaphore); //这里请求成功信号量 +1 为1} failure:^(NSURLSessionDataTask *task, NSError *error) {    dispatch_semaphore_signal(semaphore); //这里请求失败信号量 +1 为1}];dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //走到这里如果信号量为0 则不再执行下面的代码 一直等待 信号量不是0 出现 才会执行下面代码,然后信号量为 - 1
  • 这个解决了依次执行的问题 下面解决怎么知道全部执行完毕呢

4. 执行完毕问题的解决,使用KVO监听任务数是否为0

//添加监听 监听队列是否全部执行完毕[queue addObserver:self forKeyPath:@"operationCount" options:0 context:nil];-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {if ([keyPath isEqualToString:@"operationCount"]) {    NSOperationQueue *queue = (NSOperationQueue *)object;    if (queue.operationCount == 0) {        NSLog(@"全部完成");    }}}

5.至此解决了依次执行异步网络请求 的一种实现方法

0 0
原创粉丝点击