在網(wǎng)絡請求的時候有時有這種需求
兩個接口請求數(shù)據(jù)辽幌,然后我們才能做最后的數(shù)據(jù)處理。但是因為網(wǎng)絡請求是移步的 现横。我們并不知道什么時候兩個請求完成 漓拾。
通常面對這樣的需求會自然的想到 多線程
啊 阁最。表現(xiàn)真正的技術的時刻來啦,可以使用 group
隊列啊 骇两。等隊列中的請求任務都完成 速种,在通知主線程處理匯總數(shù)據(jù)嘛 。
今天我也是這么寫的低千,但是發(fā)現(xiàn)主線程并沒有等到隊列中的分線程網(wǎng)絡請求bock回調(diào)就返回了 配阵。我給block回調(diào)之前打印,確實是隊列中的任務都打印之后示血,才返回的主線程 棋傍。那么問題在哪里 ?
網(wǎng)絡請求然后處理響應數(shù)據(jù)是個耗時的操作难审,也是我們開發(fā)中常見的一種情形瘫拣,在網(wǎng)絡請求以及處理響應數(shù)據(jù)操作完畢之后我們在執(zhí)行別的操作這樣的過程也是我們開發(fā)中常見的情形。我們可以知道剔宪,
網(wǎng)絡請求的任務是提交給子線程異步處理了拂铡,網(wǎng)絡請求這樣的任務也就快速執(zhí)行完畢了,但是網(wǎng)絡請求是一個任務葱绒,處理收到的網(wǎng)絡響應又是一個任務感帅,注意不要把這兩個過程混為一談。
而收到網(wǎng)絡響應以及處理返回響應的數(shù)據(jù)并不是在子線程中執(zhí)行的地淀,我們通過在回調(diào)響應處理的block中打印當前線程失球,會發(fā)現(xiàn)回調(diào)響應處理的block是在主線程中被執(zhí)行的。
如果很熟悉block回調(diào)這種通信機制的話帮毁,就不難理解实苞,這個回調(diào)響應的block真正被調(diào)用執(zhí)行的地方應該是AFN框架的底層代碼,而這部分代碼顯然是在主線程中執(zhí)行的烈疚。
這時候黔牵,如果我們需要確定這個主線程中收到網(wǎng)絡響應的數(shù)據(jù)被處理操作結束之后,才最后執(zhí)行我們需要最后的操作爷肝。換句話說猾浦,自線程就要等待,收到一個信號灯抛,才通知主線程金赦,自己真正的完成任務了 。
這個信號就是GCD的信號量 dispatch_semaphore_t
- (void)getNetworkingData{
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)絡請求任務添加到組中
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)絡請求任務
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:urlString_1
parameters:dictionary
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"成功請求數(shù)據(jù)1:%@",[responseObject class]);
// 如果請求成功对嚼,發(fā)送信號量
dispatch_semaphore_signal(semaphore);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"失敗請求數(shù)據(jù)");
// 如果請求失敗夹抗,也發(fā)送信號量
dispatch_semaphore_signal(semaphore);
}];
// 在網(wǎng)絡請求任務成功之前,信號量等待中
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
// 將第二個網(wǎng)絡請求任務添加到組中
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)絡請求任務
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:urlString_2
parameters:dictionary
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"成功請求數(shù)據(jù)2:%@",[responseObject class]);
// 如果請求成功纵竖,發(fā)送信號量
dispatch_semaphore_signal(semaphore);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"失敗請求數(shù)據(jù)");
// 如果請求失敗漠烧,也發(fā)送信號量
dispatch_semaphore_signal(semaphore);
}];
// 在網(wǎng)絡請求任務成功之前杏愤,信號量等待中
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"完成了網(wǎng)絡請求,不管網(wǎng)絡請求失敗了還是成功了沽甥。");
});
}
這樣做的具體步驟是這樣的 声邦。在自線程隊列中 。設置的信號等待 摆舟,一直到block回調(diào)完成(主線程中)亥曹,發(fā)送信號 。子線程收到信號恨诱,然后才會通知dispatch_group_notify
子線程的請求數(shù)據(jù)真正返回了媳瞪。