9d288f08ba008c59de7fe9c4cf9679e9.jpg
需求及問題
兩個接口請求數(shù)據(jù)襟己,然后我們才能做最后的數(shù)據(jù)處理包归。但是因為網(wǎng)絡(luò)請求是異步的 课梳,因此我們并不知道什么時候兩個請求完成
通常面對這樣的需求會自然的想到 多線程 , 表現(xiàn)真正的技術(shù)的時刻來啦店量,可以使用 GCD group 隊列啊 。等隊列中的請求任務(wù)都完成 换薄,在通知主線程處理匯總數(shù)據(jù)嘛 玉雾。
網(wǎng)絡(luò)請求然后處理響應(yīng)數(shù)據(jù)是個耗時的操作,開發(fā)中常見的情形是
在網(wǎng)絡(luò)請求以及處理響應(yīng)數(shù)據(jù)操作完畢之后轻要,我們再執(zhí)行別的操作
-
網(wǎng)絡(luò)請求的任務(wù)是提交給子線程異步處理的
但是網(wǎng)絡(luò)請求是一個任務(wù)复旬,處理收到的網(wǎng)絡(luò)響應(yīng)又是一個任務(wù),注意不要把這兩個過程混為一談冲泥。
-
而收到網(wǎng)絡(luò)響應(yīng)以及處理返回響應(yīng)的數(shù)據(jù)并不是在子線程中執(zhí)行的
我們通過在回調(diào)響應(yīng)處理的block中打印當(dāng)前線程驹碍,會發(fā)現(xiàn)回調(diào)響應(yīng)處理的block是在主線程中被執(zhí)行的壁涎。
如果很熟悉block回調(diào)這種通信機制的話,就不難理解志秃,這個回調(diào)響應(yīng)的block真正被調(diào)用執(zhí)行的地方應(yīng)該是 AFN 框架的底層代碼怔球,而這部分代碼顯然是在主線程中執(zhí)行的。
這時候浮还,如果我們需要確定這個主線程中收到網(wǎng)絡(luò)響應(yīng)的數(shù)據(jù)被處理操作結(jié)束之后竟坛,才最后執(zhí)行我們需要最后的操作。
換句話說钧舌,子線程就要等待流码,收到一個信號,才通知主線程延刘,自己真正的完成任務(wù)了 。
這個信號就是GCD的信號量 dispatch_semaphore_t
上代碼
NSString *appIdKey = @"8781e4ef1c73ff20a180d3d7a42a8c04";
NSString* urlString_1 = @"http://api.openweathermap.org/data/2.5/weather";
NSString* urlString_2 = @"http://api.openweathermap.org/data/2.5/forecast/daily";
NSDictionary* dictionary =@{@"lat":@"40.04991291",
@"lon":@"116.25626162",
@"APPID" : appIdKey};
// 創(chuàng)建組
dispatch_group_t group = dispatch_group_create();
// 將第一個網(wǎng)絡(luò)請求任務(wù)添加到組中
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 創(chuàng)建信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// 開始網(wǎng)絡(luò)請求任務(wù)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:urlString_1
parameters:dictionary
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 如果請求成功六敬,發(fā)送信號量
dispatch_semaphore_signal(semaphore);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// 如果請求失敗碘赖,也發(fā)送信號量
dispatch_semaphore_signal(semaphore);
}];
// 在網(wǎng)絡(luò)請求任務(wù)成功之前,信號量等待中
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
// 將第二個網(wǎng)絡(luò)請求任務(wù)添加到組中
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 創(chuàng)建信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// 開始網(wǎng)絡(luò)請求任務(wù)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:urlString_2
parameters:dictionary
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 如果請求成功外构,發(fā)送信號量
dispatch_semaphore_signal(semaphore);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// 如果請求失敗普泡,也發(fā)送信號量
dispatch_semaphore_signal(semaphore);
}];
// 在網(wǎng)絡(luò)請求任務(wù)成功之前,信號量等待中
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
//兩個信號都收到后审编,會進(jìn)入這里
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//注:如果要對UI進(jìn)行操作撼班,第二個參數(shù)就傳dispatch_get_main_queue()
NSLog(@"完成了網(wǎng)絡(luò)請求,不管網(wǎng)絡(luò)請求失敗了還是成功了垒酬。");
});
1. 這樣做的具體步驟是這樣的 砰嘁。在自線程隊列中 。設(shè)置的信號等待 勘究,一直到block回調(diào)完成(主線程中)矮湘,發(fā)送信號 。子線程收到信號口糕,然后才會通知dispatch_group_notify 子線程的請求數(shù)據(jù)真正返回了缅阳。
2. 在使用的時候一定要想清楚哪個需要等待,哪個線程來發(fā)送景描。
af6d96dad04e0315e3d78c6c147d8018.jpeg