先看一段错误的方法:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSURLSession *session = [NSURLSession sharedSession]; dispatch_queue_t dispatchQueue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t dispatchGroup = dispatch_group_create(); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"got data from internet1"); }]; [task resume]; }); dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"got data from internet2"); }]; [task resume]; }); dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"end"); }); }
看看log的输出
2016-07-13 17:42:55.170 aaaa[4797:295528] end 2016-07-13 17:42:55.322 aaaa[4797:295574] got data from internet2 2016-07-13 17:42:55.375 aaaa[4797:295574] got data from internet1
完全没有达到效果。这是因为这里的网络请求是个异步的方法,没有等待具体的数据返回,放入的dispatch queue的 block就执行完毕了。所以没收到2个网络数据,就提前调用了dispatch_group_notify指定的结束方法。
再看正确的方法:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSURLSession *session = [NSURLSession sharedSession]; dispatch_queue_t dispatchQueue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t dispatchGroup = dispatch_group_create(); // dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ dispatch_group_enter(dispatchGroup); NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"got data from internet1"); dispatch_group_leave(dispatchGroup); }]; [task resume]; // }); // dispatch_group_async(dispatchGroup, dispatchQueue, ^(){ dispatch_group_enter(dispatchGroup); NSURLSessionDataTask *task2 = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"got data from internet2"); dispatch_group_leave(dispatchGroup); }]; [task2 resume]; // }); dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"end"); }); }
看正确是输出结果:
2016-07-13 17:46:10.282 aaaa[4847:300370] got data from internet1 2016-07-13 17:46:10.501 aaaa[4847:300370] got data from internet2 2016-07-13 17:46:10.502 aaaa[4847:300341] end
我们看看关于dispatch_group_enter 的具体说明
Calling this function increments the current count of outstanding tasks in the group. Using this function (with dispatch_group_leave) allows your application to properly manage the task reference count if it explicitly adds and removes tasks from the group by a means other than using the dispatch_group_async function. A call to this function must be balanced with a call to dispatch_group_leave. You can use this function to associate a block with more than one group at the same time.
简单的说,就是dispatch_group_enter会对group的内部计数加一,dispatch_group_leave会对group的内部计数减一,就类似以前的retain和release方法。说白了也是维护了一个计数器,只不过系统将这个计数器封装了起来,不用我们自己实现了,代码看起来更简洁,高大上了。
时间: 2024-10-11 11:55:56