ios多个网络请求之间的处理

在日常开发中我们总是会和网络打交道,从服务端拿数据渲染UI、上传数据到服务器、登陆等,那么就会遇到一些问题。eg:当用户登陆完毕后才获取数据渲染UI或者是多个网络请求从服务端拿到多个数据后,才进行下一步的操作,那么对网络请求之间顺序的控制是十分重要的,本文对这两种情况进行总结,如有不足之处,请多多指教。

情景一:多个网络请求执行(无序)完后,在执行其他操作

#define GlobalQueue dispatch_get_global_queue(0, 0)

#define MainQueue dispatch_get_main_queue()

  1. 队列组group + notify

      
      - (void)multipleRequest_NoOrder_after_executeOtherTask_byGroupNotify {
          dispatch_group_t group = dispatch_group_create();
          dispatch_group_async(group, GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求1");
          });
          dispatch_group_async(group, GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求2");
          });
          dispatch_group_async(group, GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求3");
          });
          dispatch_group_async(group, GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求4");
          });
          //当group中的任务执行完后,会调用
          dispatch_group_notify(group, MainQueue, ^{
              NSLog(@"更新UI");
          });
      }
    复制代码
  2. NSOperation + NSOperationQueue

      
      - (void)multipleRequest_NoOrder_after_executeOtherTask_byOperation {
          NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求1");
          }];
          NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求2");
          }];
          NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求3");
          }];
          NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求4");
          }];
          
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          //设置最大并发数
          queue.maxConcurrentOperationCount = [NSProcessInfo processInfo].activeProcessorCount;
          //waitUntilFinished:是否等待queue中的任务执行完后,才执行后面的代码。会阻塞当前线程
          [queue addOperations:@[block1,block2,block3,block4] waitUntilFinished:NO];
          
          //当queue中的所有任务执行完后,会调用
          [queue addBarrierBlock:^{
              NSLog(@"更新UI");
          }];
      }
    复制代码
  3. 信号量dispatch_semaphore_t

      - (void)multipleRequest_NoOrder_after_executeOtherTask_bySemaphore {
        //传入的值必须大于等于0
          dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
          dispatch_async(GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求1");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求2");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求3");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              sleep(1);
              NSLog(@"网络请求4");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(MainQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              NSLog(@"更新UI");
          });
      }
    复制代码
  4. 栅栏函数barrier

      - (void)multipleRequest_NoOrder_after_executeOtherTask_byBarrier {
          dispatch_queue_t queue = dispatch_queue_create("ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
          dispatch_async(queue, ^{
              sleep(1);
              NSLog(@"网络请求1");
          });
          dispatch_async(queue, ^{
              sleep(1);
              NSLog(@"网络请求2");
          });
          dispatch_async(queue, ^{
              sleep(1);
              NSLog(@"网络请求3");
          });
          dispatch_async(queue, ^{
              sleep(1);
              NSLog(@"网络请求4");
          });
          //坑点:不能用全局并发队列,栅栏函数会失效并且栅栏函数只能用于自定义创建的并发队列,如果传递dispatch_get_global_queue(0, 0),那么dispatch_barrier_async等价于dispatch_async
          dispatch_barrier_async(queue, ^{
              NSLog(@"更新UI");
          });
      }
    复制代码

情景二:多个网络请求执行(有序)完后,在执行其他操作

  1. 队列组group + enter + leave

      
      - (void)multipleRequest_InOrder_after_executeOtherTask_byGroup {
          dispatch_group_t group = dispatch_group_create();
      ​
          dispatch_group_enter(group);
          [self request:@"1" finished:^{
              dispatch_group_leave(group);
          }];
          
          dispatch_group_enter(group);
          [self request:@"2" finished:^{
              dispatch_group_leave(group);
          }];
          
          dispatch_group_enter(group);
          [self request:@"3" finished:^{
              dispatch_group_leave(group);
          }];
          
          dispatch_group_enter(group);
          [self request:@"4" finished:^{
              dispatch_group_leave(group);
          }];
          dispatch_group_notify(group, MainQueue, ^{
              NSLog(@"更新UI");
          });
      }
      - (void)request:(NSString *)parama finished:(void(^)(void))finished {
          dispatch_async(GlobalQueue, ^{
              NSLog(@"网络请求%@",parama);
              if(finished) { finished(); }
          });
       
      }
    复制代码
  2. 信号量

      
      - (void)multipleRequest_InOrder_after_executeOtherTask_bySemaphore {
          dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
          dispatch_async(GlobalQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              sleep(1);
              NSLog(@"网络请求1");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              sleep(1);
              NSLog(@"网络请求2");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              sleep(1);
              NSLog(@"网络请求3");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(GlobalQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              sleep(1);
              NSLog(@"网络请求4");
              dispatch_semaphore_signal(semaphore);
          });
          dispatch_async(MainQueue, ^{
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              NSLog(@"更新UI");
              dispatch_semaphore_signal(semaphore);
          });
      }
    复制代码
  3. NSOperation + NSOperationQueue(添加任务之间的依赖关系)

      
      - (void)multipleRequest_InOrder_after_executeOtherTask_byOperation {
          NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求1");
          }];
          NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求2");
          }];
          NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
              sleep(1);
              NSLog(@"网络请求3");
          }];
          NSBlockOperation *block4 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"网络请求4");
              sleep(1);
          }];
          [block4 addDependency:block3];
          [block3 addDependency:block2];
          [block2 addDependency:block1];
          NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
          [operationQueue addOperations:@[block1,block2,block3,block4] waitUntilFinished:NO];
          //会等到queue中的任务执行完后才会调用
          [operationQueue addBarrierBlock:^{
              dispatch_async(dispatch_get_main_queue(), ^{
                  NSLog(@"刷新UI");
              });
          }];
      }
    复制代码
  4. 条件NSConditionLock

      - (void)multipleRequest_InOrder_after_executeOtherTask_byConditionLock {
          NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1];
          dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
          /**
           *lockWhenCondition(加锁):当特定条件值时,才会加锁,否则线程休眠
           *unlockWithCondition(解锁):解锁并将条件值设置为传入的值
           */
          dispatch_async(globalQueue, ^{
              [conditionLock lockWhenCondition:1];
              NSLog(@"网络请求1");
              sleep(1);
              [conditionLock unlockWithCondition:2];
          });
          dispatch_async(globalQueue, ^{
              [conditionLock lockWhenCondition:2];
              NSLog(@"网络请求2");
              sleep(1);
              [conditionLock unlockWithCondition:3];
          });
          dispatch_async(globalQueue, ^{
              [conditionLock lockWhenCondition:3];
              NSLog(@"网络请求3");
              sleep(1);
              [conditionLock unlockWithCondition:4];
          });
          dispatch_async(globalQueue, ^{
              [conditionLock lockWhenCondition:4];
              NSLog(@"网络请求4");
              sleep(1);
              [conditionLock unlockWithCondition:1];
              dispatch_async(dispatch_get_main_queue(), ^{
                  NSLog(@"刷新UI");
              });
          });
      }
    复制代码

上面是本人目前掌握的解决方案。如有更好的方式,欢迎大家进行评论交流。

猜你喜欢

转载自juejin.im/post/7078892935093157902