iOS GCD之项目实战
2019-06-19 本文已影响0人
不会写代码的尬先生
实际开发中我们可能会遇到这种需求:等待某几个网络请求结束再进行后续操作,比如一个页面需要先请求三个接口,都拿到数据以后再去做页面的渲染。
可能我们会想到用gcd的dispatch_group_t,再异步并发请求接口,最后notify处理,但运行结果并不是我们预想的那样,而是先打印了notifyblock里的内容,才打印两个网络请求的内容,这是因为网络请求本身就是异步的,此时group的notify并不会真正等到网络请求结束才去处理notify。
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, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求一");
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_async(group, queue, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求二");
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"请求完成");
});
});
打印结果:
请求完成
请求二或请求三(异步,不确定先后)
介绍两种实现方式
一是用 dispatch_group_enter和dispatch_group_leave在每次网络请求成对使用
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求一");
dispatch_group_leave(group);
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求二");
dispatch_group_leave(group);
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"请求完成");
});
});
打印顺序:
先打印 请求二或请求一(异步乱序)
最后打印 请求完成
第二种是用dispatch_group_t加dispatch_semaphore_t信号量
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, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求一");
dispatch_semaphore_signal(semaphore);
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_async(group, queue, ^{
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys:@"121", @"id",nil];
[CSNetWoring sendPostNetWorkWithUrl:SPORT_ORUN_RESOURCE parameters:param progressBlock:^(NSProgress *progress) {
} successBlock:^(id data) {
NSLog(@"请求二");
dispatch_semaphore_signal(semaphore);
} failureBlock:^(NSString *error) {
}];
});
dispatch_group_notify(group, queue, ^{
NSLog(@"请求三");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"请求四");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"请求完成");
});
});
打印顺序:
请求三
请求一和请求二乱序
请求四
请求完成
dispatch_semaphore_wait会一直阻塞线程直到网络请求成功收到dispatch_semaphore_signal信号