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

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:(NSDictionaryid> *)change context:(void *)context {

if ([keyPath isEqualToString:@"operationCount"]) {
    NSOperationQueue *queue = (NSOperationQueue *)object;
    if (queue.operationCount == 0) {
        NSLog(@"全部完成");
    }
}
}

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

你可能感兴趣的:(iOS随笔)