iOS中多個(gè)網(wǎng)絡(luò)請求的同步問題總結(jié)

場景描述:我們同時(shí)發(fā)出了a、b琳水、c 3個(gè)網(wǎng)絡(luò)請求肆糕,我們希望在a、b在孝、c 3個(gè)網(wǎng)絡(luò)請求都結(jié)束的時(shí)候獲得一個(gè)通知诚啃。
常見解決方法:通過度娘目前找到兩種做法;1浑玛、通過添加標(biāo)識來判斷請求是否全部結(jié)束 2绍申、dispatch_group + 信號量
本篇文章demo

1、添加標(biāo)識的解決方法

在遇到這個(gè)問題時(shí)首先想到了猿題庫團(tuán)隊(duì)開源的網(wǎng)絡(luò)框架YTKNetwork顾彰,然后閱讀源碼發(fā)現(xiàn)YTKNetwork是通過添加標(biāo)識來實(shí)現(xiàn)網(wǎng)絡(luò)請求的批量請求處理极阅;
話不多說直接上代碼在YTKNetwork里負(fù)責(zé)進(jìn)行網(wǎng)絡(luò)批處理請求的是YTKBatchRequest類,下面看下它的使用示例:

- (void)sendBatchRequest {
    GetImageApi *a = [[GetImageApi alloc] initWithImageId:@"1.jpg"];
    GetImageApi *b = [[GetImageApi alloc] initWithImageId:@"2.jpg"];
    GetImageApi *c = [[GetImageApi alloc] initWithImageId:@"3.jpg"];
    GetUserInfoApi *d = [[GetUserInfoApi alloc] initWithUserId:@"123"];
    YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[a, b, c, d]];
    [batchRequest startWithCompletionBlockWithSuccess:^(YTKBatchRequest *batchRequest) {
        NSLog(@"succeed");
        NSArray *requests = batchRequest.requestArray;
        GetImageApi *a = (GetImageApi *)requests[0];
        GetImageApi *b = (GetImageApi *)requests[1];
        GetImageApi *c = (GetImageApi *)requests[2];
        GetUserInfoApi *user = (GetUserInfoApi *)requests[3];
        // deal with requests result ...
        NSLog(@"%@, %@, %@, %@", a, b, c, user);
    } failure:^(YTKBatchRequest *batchRequest) {
        NSLog(@"failed");
    }];
}

先調(diào)用初始化方法把4個(gè)網(wǎng)絡(luò)請求的實(shí)例塞進(jìn)去YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[a, b, c, d]]涨享,看下這個(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ù)字面很好理解是用來記錄請求完成的個(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ò)請求結(jié)束的回調(diào)代理方法厕隧,完成后_finishedCount計(jì)數(shù)加1奔脐,然后和保存網(wǎng)絡(luò)請求實(shí)例的數(shù)組元素個(gè)數(shù)進(jìn)行比較如果相等說明所有的請求都已經(jīng)完成,調(diào)用回調(diào)的代理方法及block請求結(jié)束吁讨。

然后YTKNetwork對于批量網(wǎng)絡(luò)請求失敗的處理是髓迎,只要一個(gè)失敗就立即停止請求,調(diào)用失敗回調(diào):

- (void)requestFailed:(YTKRequest *)request {
    [self toggleAccessoriesWillStopCallBack];
    // Stop
    for (YTKRequest *req in _requestArray) {//遍歷請求實(shí)例數(shù)組
        [req stop];//停止請求
    }
    // 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è)變量記錄完成請求的個(gè)數(shù)建丧,然后在單個(gè)網(wǎng)絡(luò)請求結(jié)束回調(diào)的時(shí)候判斷當(dāng)前完成的網(wǎng)絡(luò)請求個(gè)數(shù)是否和總的網(wǎng)絡(luò)請求個(gè)數(shù)相等排龄,如果相等則說明請求結(jié)束。

2翎朱、dispatch_group + 信號量

參考文章
參考文章采用的是group + 信號量橄维,下面示例采用dispatch_group_enter尺铣、dispatch_group_leave實(shí)現(xiàn)詳見 本篇文章demo

- (void)loadRequest1
{
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_enter(dispatchGroup);
    [MALAFNManger getDataWithUrl:Url1 parameters:nil finish:^(RequestResult *result) {</br>
        
        NSLog(@"第一個(gè)請求完成");
        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ò)請求結(jié)束后回調(diào)是在主線程如果sleep放在外面會(huì)阻塞主線程
            NSLog(@"第二個(gè)請求完成");
            dispatch_group_leave(dispatchGroup);
        });
        
    } des:@"第二個(gè)url"];
    
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        
        NSLog(@"請求完成");
    });
}

dispach_group的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末争舞,一起剝皮案震驚了整個(gè)濱河市凛忿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌竞川,老刑警劉巖店溢,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異流译,居然都是意外死亡逞怨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門福澡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驹马,你說我怎么就攤上這事革砸。” “怎么了糯累?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵算利,是天一觀的道長。 經(jīng)常有香客問我泳姐,道長效拭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任胖秒,我火速辦了婚禮缎患,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阎肝。我一直安慰自己挤渔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布风题。 她就那樣靜靜地躺著判导,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沛硅。 梳的紋絲不亂的頭發(fā)上眼刃,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機(jī)與錄音摇肌,去河邊找鬼擂红。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朦蕴,可吹牛的內(nèi)容都是我干的篮条。 我是一名探鬼主播弟头,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涉茧!你這毒婦竟也來了赴恨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤伴栓,失蹤者是張志新(化名)和其女友劉穎伦连,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钳垮,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惑淳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饺窿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歧焦。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肚医,靈堂內(nèi)的尸體忽然破棺而出绢馍,到底是詐尸還是另有隱情,我是刑警寧澤肠套,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布舰涌,位于F島的核電站,受9級特大地震影響你稚,放射性物質(zhì)發(fā)生泄漏瓷耙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一刁赖、第九天 我趴在偏房一處隱蔽的房頂上張望搁痛。 院中可真熱鬧,春花似錦乾闰、人聲如沸落追。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轿钠。三九已至,卻和暖如春病苗,著一層夾襖步出監(jiān)牢的瞬間疗垛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工硫朦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贷腕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像泽裳,于是被迫代替她去往敵國和親瞒斩。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用涮总,...
    LZM輪回閱讀 3,329評論 0 6
  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP胸囱、TCP、Http瀑梗、Socket烹笔、X...
    Carden閱讀 4,351評論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,990評論 0 7
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,360評論 0 35
  • 今天微信小程序正式發(fā)布,他到底是怎樣的抛丽,未來又有多廣闊谤职,讓我們拭目以待。 以下是我對微信小程序一點(diǎn)想法 小程序會(huì)是...
    冰糖和葫蘆閱讀 180評論 0 0