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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容