您的当前位置:首页正文

iOS 多个网络请求并发执行的解决方案

来源:华佗小知识

在项目中往往会遇到这种需求:UI 的更新要在2~3个网络请求后才执行.这里提供两种执行方案.
一.利用 GCD
通过 gcd_group可以解决这个问题.具体做法如下

//
// ViewController.m
// tableview
//
// Created by myMac on 16/12/26.
// Copyright © 2016年 myMac. All rights reserved.
//

import "ViewController.h"

typedef void(^FinishNetwork)();

@interface ViewController ()

@property (nonatomic, copy ) FinishNetwork block;
@property (nonatomic, copy ) NSString *string1;
@property (nonatomic, copy ) NSString *string2;
@property (nonatomic, copy ) NSString *string3;

@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self initData];
    }
  • (void)initData {

    // 创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    // 创建全局并行
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{

      // 请求一
      //这里通过 block 表示请求结束,并标记一个信号量
      [self getList1:^{
          
          dispatch_semaphore_signal(semaphore);
      }];
    

    });
    dispatch_group_async(group, queue, ^{

      // 请求二
      [self getList2:^{
          
          dispatch_semaphore_signal(semaphore);
      }];
    

    });
    dispatch_group_async(group, queue, ^{

      // 请求三
      [self getList3:^{
          
          dispatch_semaphore_signal(semaphore);
      }];
    

    });

    dispatch_group_notify(group, queue, ^{

      //在这里 进行请求后的方法
      NSLog(@"string1:___%@", _string1);
      NSLog(@"string2:___%@", _string2);
      NSLog(@"string3:___%@", _string3);
      
      // 三个请求对应三次信号等待
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    

    });

}

  • (void)getList1:(FinishNetwork)block {

    NSLog(@"加载列表1");
    self.string1 = @"加载列表1";

}

  • (void)getList2:(FinishNetwork)block {

    NSLog(@"加载列表2");
    self.string2 = @"加载列表2";

}

  • (void)getList3:(FinishNetwork)block {

    NSLog(@"加载列表3");
    self.string3 = @"加载列表3";

}

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

@end

20161229132112431.png

二.通过 RAC
利用 RAC 的 merge 也可以解决这个问题,具体做法如下
ViewController

[[RACSignal merge:@[[TestViewModel fetchList1], [TestViewModel fetchList2]]] subscribeNext:^(id x) {

    NSLog(@"%@", x);
    if (!_string1.length) {
        self.string1 = x;
    } else {
        self.string2 = x;
    }
    
} completed:^{
    NSLog(@"string1: %@\nstring2: %@ \n", _string1, _string2);
}];

ViewModel

import "TestViewModel.h"

@implementation TestViewModel

  • (RACSignal *)fetchList1 {

    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

      [subscriber sendNext:@"请求1"];
      [subscriber sendCompleted];
      return nil;
    

    }];

}

  • (RACSignal *)fetchList2 {

    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

      [subscriber sendNext:@"请求2"];
      [subscriber sendCompleted];
      return nil;
    

    }];

}
@end

20161229143724794.png

另外,通过下面的方法也可以实现
<span style="font-size:18px;">/// Like -rac_liftSelector:withSignals:, but accepts an array instead of
/// a variadic list of arguments.

  • (RACSignal *)rac_liftSelector:(SEL)selector withSignalsFromArray:(NSArray *)signals;</span>

具体实现代码
[self rac_liftSelector:@selector(responseA:B:) withSignalsFromArray:@[[TestViewModel fetchList1], [TestViewModel fetchList2]]];

  • (void)responseA:(id)a B:(id)b {
    NSLog(@"%@, %@", a, b);
    }
    打印出的结果
20161229144215293.png