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
另外,通过下面的方法也可以实现
<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);
}
打印出的结果