詳解iOS中多個(gè)網(wǎng)絡(luò)請(qǐng)求的同步問(wèn)題總結(jié)
場(chǎng)景描述:我們同時(shí)發(fā)出了a、b、c 3個(gè)網(wǎng)絡(luò)請(qǐng)求,我們希望在a、b、c 3個(gè)網(wǎng)絡(luò)請(qǐng)求都結(jié)束的時(shí)候獲得一個(gè)通知。
常見(jiàn)解決方法:通過(guò)度娘目前找到兩種做法;1、通過(guò)添加標(biāo)識(shí)來(lái)判斷請(qǐng)求是否全部結(jié)束 2、dispatch_group + 信號(hào)量
1、添加標(biāo)識(shí)的解決方法
在遇到這個(gè)問(wèn)題時(shí)首先想到了唐巧大大的猿題庫(kù)團(tuán)隊(duì)開(kāi)源的網(wǎng)絡(luò)框架YTKNetwork,然后閱讀源碼發(fā)現(xiàn)YTKNetwork是通過(guò)添加標(biāo)識(shí)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求的批量請(qǐng)求處理;
話不多說(shuō)直接上代碼在YTKNetwork里負(fù)責(zé)進(jìn)行網(wǎng)絡(luò)批處理請(qǐng)求的是YTKBatchRequest類,下面看下它的使用示例:
YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[a, b, c, d]];
先調(diào)用初始化方法把4個(gè)網(wǎng)絡(luò)請(qǐng)求的實(shí)例塞進(jìn)去,看下這個(gè)初始化方法
- (id)initWithRequestArray:(NSArray )requestArray { self = [super init]; if (self) { _requestArray = [requestArray copy]; _finishedCount = 0; for (YTKRequest req in _requestArray) { if (![req isKindOfClass:[YTKRequest class]]) { YTKLog(@"Error, request item must be YTKRequest instance."); return nil; } } } return self; }
我們看到有一個(gè)_finishedCount的變量根據(jù)字面很好理解是用來(lái)記錄請(qǐng)求完成的個(gè)數(shù),然后我們?nèi)炙严逻@個(gè)變量,發(fā)現(xiàn)只有在下面的這個(gè)方法中用到了這個(gè)變量
- (void)requestFinished:(YTKRequest *)request { _finishedCount++; if (_finishedCount == _requestArray.count) { [self toggleAccessoriesWillStopCallBack]; if ([_delegate respondsToSelector:@selector(batchRequestFinished:)]) { [_delegate batchRequestFinished:self]; } if (_successCompletionBlock) { _successCompletionBlock(self); } [self clearCompletionBlock]; [self toggleAccessoriesDidStopCallBack]; [[YTKBatchRequestAgent sharedInstance] removeBatchRequest:self]; } }
上述方法是網(wǎng)絡(luò)請(qǐng)求結(jié)束的回調(diào)代理方法,完成后_finishedCount計(jì)數(shù)加1,然后和保存網(wǎng)絡(luò)請(qǐng)求實(shí)例的數(shù)組元素個(gè)數(shù)進(jìn)行比較如果相等說(shuō)明所有的請(qǐng)求都已經(jīng)完成,調(diào)用回調(diào)的代理方法及block請(qǐng)求結(jié)束。
然后YTKNetwork對(duì)于批量網(wǎng)絡(luò)請(qǐng)求失敗的處理是,只要一個(gè)失敗就立即停止請(qǐng)求,調(diào)用失敗回調(diào):
- (void)requestFailed:(YTKRequest )request { [self toggleAccessoriesWillStopCallBack]; // Stop for (YTKRequest req in _requestArray) {//遍歷請(qǐng)求實(shí)例數(shù)組 [req stop];//停止請(qǐng)求 } // Callback //回調(diào) if ([_delegate respondsToSelector:@selector(batchRequestFailed:)]) { [_delegate batchRequestFailed:self]; } if (_failureCompletionBlock) { _failureCompletionBlock(self); } // Clear [self clearCompletionBlock]; [self toggleAccessoriesDidStopCallBack]; [[YTKBatchRequestAgent sharedInstance] removeBatchRequest:self]; }
總結(jié):YTKNetwork的做法大致就是用一個(gè)變量記錄完成請(qǐng)求的個(gè)數(shù),然后在單個(gè)網(wǎng)絡(luò)請(qǐng)求結(jié)束回調(diào)的時(shí)候判斷當(dāng)前完成的網(wǎng)絡(luò)請(qǐng)求個(gè)數(shù)是否和總的網(wǎng)絡(luò)請(qǐng)求個(gè)數(shù)相等,如果相等則說(shuō)明請(qǐng)求結(jié)束。
2、dispatch_group + 信號(hào)量
參考文章采用的是group + 信號(hào)量,下面示例采用dispatch_group_enter、dispatch_group_leave實(shí)現(xiàn)詳見(jiàn) 本篇文章demo。
- (void)loadRequest1 { dispatch_group_t dispatchGroup = dispatch_group_create(); dispatch_group_enter(dispatchGroup); [MALAFNManger getDataWithUrl:Url1 parameters:nil finish:^(RequestResult result) { NSLog(@"第一個(gè)請(qǐng)求完成"); dispatch_group_leave(dispatchGroup); } des:@"第一個(gè)url"]; dispatch_group_enter(dispatchGroup); [MALAFNManger getDataWithUrl:Url2 parameters:nil finish:^(RequestResult result) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ sleep(10);//網(wǎng)絡(luò)請(qǐng)求結(jié)束后回調(diào)是在主線程如果sleep放在外面會(huì)阻塞主線程 NSLog(@"第二個(gè)請(qǐng)求完成"); dispatch_group_leave(dispatchGroup); }); } des:@"第二個(gè)url"]; dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"請(qǐng)求完成"); }); }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于iOS開(kāi)發(fā)證書(shū)和配置文件的使用
下面小編就為大家分享一篇基于iOS開(kāi)發(fā)證書(shū)和配置文件的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01iOS給border設(shè)置漸變色的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于iOS給border設(shè)置漸變色的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03iOS基于UITableView實(shí)現(xiàn)多層展開(kāi)與收起
這篇文章主要為大家詳細(xì)介紹了iOS基于UITableView實(shí)現(xiàn)多層展開(kāi)與收起的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03iOS通過(guò)block在兩個(gè)頁(yè)面間傳值的方法
不知道大家有沒(méi)有發(fā)現(xiàn),在實(shí)際開(kāi)發(fā)中使用block的地方特別多,block比delegate和notification有著更簡(jiǎn)潔的優(yōu)勢(shì),下面這篇文章我們來(lái)簡(jiǎn)單了解一下block在兩個(gè)頁(yè)面之間的傳值。有需要的朋友們可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11總結(jié)iOS開(kāi)發(fā)中的斷點(diǎn)續(xù)傳與實(shí)踐
本文先從斷點(diǎn)續(xù)傳問(wèn)題開(kāi)始,介紹斷點(diǎn)續(xù)傳概述和原理。接著結(jié)合筆者調(diào)研中嘗試的 AFHTTPRequestOpeartion,簡(jiǎn)單分析源碼。最后分別基于 NSURLConnection,NSURLSessionDataTask 和 NSURLSessionDownloadTask 去實(shí)現(xiàn)應(yīng)用重啟情況下的斷點(diǎn)續(xù)傳。下面一起來(lái)看看。2016-07-07iOS App項(xiàng)目中引入SQLite數(shù)據(jù)庫(kù)的教程
SQLite是一個(gè)極輕的嵌入式數(shù)據(jù)庫(kù),在應(yīng)用程序中捆綁使用可以更方便地幫助操控關(guān)系型數(shù)據(jù),這里我們就來(lái)看一下iOS App項(xiàng)目中引入SQLite數(shù)據(jù)庫(kù)的教程2016-06-06iOS系統(tǒng)和微信中不支持audio自動(dòng)播放問(wèn)題的解決方法
最近在微信端開(kāi)發(fā)H5的時(shí)候,audio標(biāo)簽在蘋果機(jī)上無(wú)法進(jìn)行自動(dòng)播放,查找相關(guān)資料終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于iOS系統(tǒng)和微信中不支持audio自動(dòng)播放問(wèn)題的解決方法,需要的朋友可以參考下。2017-09-09