iOS開發 GCD訊號量實現AFNetworking的順序請求

weixin_33670713發表於2018-12-20

[圖片上傳失敗...(image-97ada5-1545274514848)]

最近遇到一個☝️問題。一個頁面有多個介面,需要請求完介面後,在把介面資料組裝排序後再展示。於是我第一反應是使用GCD_group或者barrier.經過實踐失敗了。最後經過多方調研,使用dispatch_semaphore解決了這個問題,但是也有遇到坑。。。

首先貼出解決方案
#1

   //    /建立訊號量為0
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, queue, ^{
        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/journalismApi" param:nil success:^(id data) {
//            訊號量?+1
            dispatch_semaphore_signal(semaphore);
            NSLog(@"1請求成功");
        } failure:^(NSInteger resultId, NSString *errorMsg) {
//            訊號量?+1
            dispatch_semaphore_signal(semaphore);
        }];  
    });

    dispatch_group_async(group, queue, ^{
        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinApi?type=1&page=1" param:nil success:^(id data) {
            //            訊號量?+1
            dispatch_semaphore_signal(semaphore);
            NSLog(@"2請求成功");
        } failure:^(NSInteger resultId, NSString *errorMsg) {
            //            訊號量?+1
            dispatch_semaphore_signal(semaphore);
        }];
    });

    dispatch_group_notify(group, queue, ^{
//        訊號量 -1 為0時wait會阻塞執行緒
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"訊號量為0");
        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinCommentApi?id=27610708&page=1" param:nil success:^(id data) {
            NSLog(@"3請求成功");
        } failure:^(NSInteger resultId, NSString *errorMsg) {
        }];
    });

列印結果1或2請求結束後才會請求3

2018-09-03 21:49:47.309334+0800 訊號量[20350:707280] 2請求成功
2018-09-03 21:49:48.299139+0800 訊號量[20350:707280] 1請求成功
2018-09-03 21:49:48.299139+0800 訊號量[20350:707371] 訊號量為0
2018-09-03 21:49:48.640118+0800 訊號量[20350:707280] 3請求成功

#2

  dispatch_queue_t queue = dispatch_queue_create("ben", NULL);
    dispatch_async(queue, ^{
         NSLog(@"current1:%@",[NSThread currentThread]);
        dispatch_semaphore_t  semaphore = dispatch_semaphore_create(0);
        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/journalismApi" param:nil success:^(id data) {
            dispatch_semaphore_signal(semaphore);
            NSLog(@"1請求成功");
        } failure:^(NSInteger resultId, NSString *errorMsg) {
            dispatch_semaphore_signal(semaphore);
        }];

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //等待訊號,當訊號總量少於0 的時候就會一直等待 ,否則就可以正常的執行,並讓訊號總量-1

        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinApi?type=1&page=1" param:nil success:^(id data) {
            dispatch_semaphore_signal(semaphore);
            NSLog(@"2請求成功");

        } failure:^(NSInteger resultId, NSString *errorMsg) {
            dispatch_semaphore_signal(semaphore);
        }];
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //等待訊號,當訊號總量少於0 的時候就會一直等待 ,否則就可以正常的執行,並讓訊號總量-1

        [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinCommentApi?id=27610708&page=1" param:nil success:^(id data) {
            NSLog(@"3請求成功");
        } failure:^(NSInteger resultId, NSString *errorMsg) {

        }];

    });

列印結果順序執行1,2,3

2018-09-03 21:52:34.881525+0800 訊號量[20448:711755] 1請求成功
2018-09-03 21:52:35.659227+0800 訊號量[20448:711755] 2請求成功
2018-09-03 21:52:35.951249+0800 訊號量[20448:711755] 3請求成功

遇到的坑

 NSLog(@"current1:%@",[NSThread currentThread]);

    dispatch_semaphore_t  semaphore = dispatch_semaphore_create(0);
    [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinApi?type=1&page=1" param:nil success:^(id data) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"2請求成功");

    } failure:^(NSInteger resultId, NSString *errorMsg) {
        dispatch_semaphore_signal(semaphore);
    }];
    NSLog(@"你會來這兒嗎1");
    NSLog(@"current1:%@",[NSThread currentThread]);
   //    #######阻塞了主執行緒
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //等待訊號,當訊號總量少於0 的時候就會一直等待 ,否則就可以正常的執行,並讓訊號總量-1

    NSLog(@"你會來這兒嗎2");
    [ATBaseRequest getRequestWithMethod:@"https://www.apiopen.top/satinCommentApi?id=27610708&page=1" param:nil success:^(id data) {

        NSLog(@"3請求成功");

    } failure:^(NSInteger resultId, NSString *errorMsg) {

    }];

列印你會發現卡在了NSLog(@"你會來這兒嗎1"); 這裡
原因:阻塞了主執行緒。

2018-09-03 21:56:36.863662+0800 訊號量[20583:717991] current1:<NSThread: 0x604000076680>{number = 1, name = main}
2018-09-03 21:56:36.961266+0800 訊號量[20583:717991] 你會來這兒嗎1
2018-09-03 21:56:36.961413+0800 訊號量[20583:717991] current1:<NSThread: 0x604000076680>{number = 1, name = main}

參考部落格iOS開發 多執行緒的高階應用(一)

demo傳送門:GitHub

作者:本本的開心牧場
連結:https://www.jianshu.com/p/72843289ad5d
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

相關文章