詳解iOS中多個網(wǎng)絡請求的同步問題總結
場景描述:我們同時發(fā)出了a、b、c 3個網(wǎng)絡請求,我們希望在a、b、c 3個網(wǎng)絡請求都結束的時候獲得一個通知。
常見解決方法:通過度娘目前找到兩種做法;1、通過添加標識來判斷請求是否全部結束 2、dispatch_group + 信號量
1、添加標識的解決方法
在遇到這個問題時首先想到了唐巧大大的猿題庫團隊開源的網(wǎng)絡框架YTKNetwork,然后閱讀源碼發(fā)現(xiàn)YTKNetwork是通過添加標識來實現(xiàn)網(wǎng)絡請求的批量請求處理;
話不多說直接上代碼在YTKNetwork里負責進行網(wǎng)絡批處理請求的是YTKBatchRequest類,下面看下它的使用示例:
YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[a, b, c, d]];
先調用初始化方法把4個網(wǎng)絡請求的實例塞進去,看下這個初始化方法
- (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; }
我們看到有一個_finishedCount的變量根據(jù)字面很好理解是用來記錄請求完成的個數(shù),然后我們?nèi)炙严逻@個變量,發(fā)現(xiàn)只有在下面的這個方法中用到了這個變量
- (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)絡請求結束的回調代理方法,完成后_finishedCount計數(shù)加1,然后和保存網(wǎng)絡請求實例的數(shù)組元素個數(shù)進行比較如果相等說明所有的請求都已經(jīng)完成,調用回調的代理方法及block請求結束。
然后YTKNetwork對于批量網(wǎng)絡請求失敗的處理是,只要一個失敗就立即停止請求,調用失敗回調:
- (void)requestFailed:(YTKRequest )request { [self toggleAccessoriesWillStopCallBack]; // Stop for (YTKRequest req in _requestArray) {//遍歷請求實例數(shù)組 [req stop];//停止請求 } // Callback //回調 if ([_delegate respondsToSelector:@selector(batchRequestFailed:)]) { [_delegate batchRequestFailed:self]; } if (_failureCompletionBlock) { _failureCompletionBlock(self); } // Clear [self clearCompletionBlock]; [self toggleAccessoriesDidStopCallBack]; [[YTKBatchRequestAgent sharedInstance] removeBatchRequest:self]; }
總結:YTKNetwork的做法大致就是用一個變量記錄完成請求的個數(shù),然后在單個網(wǎng)絡請求結束回調的時候判斷當前完成的網(wǎng)絡請求個數(shù)是否和總的網(wǎng)絡請求個數(shù)相等,如果相等則說明請求結束。
2、dispatch_group + 信號量
參考文章采用的是group + 信號量,下面示例采用dispatch_group_enter、dispatch_group_leave實現(xiàn)詳見 本篇文章demo。
- (void)loadRequest1 { dispatch_group_t dispatchGroup = dispatch_group_create(); dispatch_group_enter(dispatchGroup); [MALAFNManger getDataWithUrl:Url1 parameters:nil finish:^(RequestResult result) { NSLog(@"第一個請求完成"); dispatch_group_leave(dispatchGroup); } des:@"第一個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)絡請求結束后回調是在主線程如果sleep放在外面會阻塞主線程 NSLog(@"第二個請求完成"); dispatch_group_leave(dispatchGroup); }); } des:@"第二個url"]; dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ NSLog(@"請求完成"); }); }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
iOS基于UITableView實現(xiàn)多層展開與收起
這篇文章主要為大家詳細介紹了iOS基于UITableView實現(xiàn)多層展開與收起的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03iOS App項目中引入SQLite數(shù)據(jù)庫的教程
SQLite是一個極輕的嵌入式數(shù)據(jù)庫,在應用程序中捆綁使用可以更方便地幫助操控關系型數(shù)據(jù),這里我們就來看一下iOS App項目中引入SQLite數(shù)據(jù)庫的教程2016-06-06iOS系統(tǒng)和微信中不支持audio自動播放問題的解決方法
最近在微信端開發(fā)H5的時候,audio標簽在蘋果機上無法進行自動播放,查找相關資料終于解決了,所以下面這篇文章主要給大家介紹了關于iOS系統(tǒng)和微信中不支持audio自動播放問題的解決方法,需要的朋友可以參考下。2017-09-09