「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」
前言
网络请求大部分情况下, 大家都是使用异步的方式去请求, 这样不会界面的主线程的卡住的情况发生, 但是在有些特殊的情况下, 是需求同时多个请求去请求, 并且需要这几个请求都返回的时候才能继续后续的操作, 每个请求又都是异步的, 那么该如何处理这种情况呢?
这种情景还是很多的, 我们可以通过过使用 # dispatch_semaphore_t
信号量的方式来让多个请求去执行, 然后等多个请求完成后, 收到信号量的信号来执行下一步操作.
实践
信号量通过是两个函数同时使用的
// 创建一个信号,value:信号量
dispatch_semaphore_create(<#long value#>)
// 使某个信号的信号量+1
dispatch_semaphore_signal(<#dispatch_semaphore_t dsema#>)
// 某个信号进行等待或等待降低信号量 timeout:等待时间,永远等待为 DISPATCH_TIME_FOREVER
dispatch_semaphore_wait(<#dispatch_semaphore_t dsema#>, <#dispatch_time_t timeout#>)
复制代码
dispatch_semaphore_create
使用这个函数来创建一个信号量
dispatch_semaphore_signal
这个函数的作用是使信号量增加1
dispatch_semaphore_wait
这个函数的作用是 等待信号量 阻断下一步的操作, 等信号量降低之后再执行后续操作
实战过程可能是这样的
- (NSDictionary *)request {
__block NSDictionary *response = @{};
dispatch_semaphore_t sp = dispatch_semaphore_create(0);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", nil];
NSString *url = @"http://www.baidu.com";
[manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
response = responseObject;
dispatch_semaphore_signal(sp);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
dispatch_semaphore_signal(sp);
}];
dispatch_semaphore_wait(sp, DISPATCH_TIME_FOREVER);
return response;
}
复制代码
这里是一个示例的请求范例, 但是会发现一个问题, 主线程被卡住, 无法执行.
具体的原因是因为afn
在拿到返回的数据时, 会回调到主线程, 而现在主线程已经被阻塞, 从而无法实现所想要功能.
如何解决这个问题? 其实很简单, 将afn
的回调放到子线程中就可以解决
- (NSDictionary *)request {
__block NSDictionary *response = @{};
dispatch_semaphore_t sp = dispatch_semaphore_create(0);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", nil];
// 给manager一个自己的线程
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSString *url = @"http://www.baidu.com";
[manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
response = responseObject;
dispatch_semaphore_signal(sp);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
dispatch_semaphore_signal(sp);
}];
dispatch_semaphore_wait(sp, DISPATCH_TIME_FOREVER);
return response;
}
复制代码
这样就可以完美的解决这个问题了.
结语
当然这仅仅是一种解决的方案, 还有很多中解决方案使用队列的方式等, 希望这篇文章能帮到你.