iOS開發(fā)技巧: 將異步方法封裝成同步方法

在開發(fā)中我們經(jīng)常會(huì)遇到異步方法,在設(shè)計(jì)程序邏輯的時(shí)候有些操作依賴于異步的回調(diào)結(jié)果,有時(shí)候我們不得不把一個(gè)原本內(nèi)聚的邏輯通過代理或者回調(diào)的方式打散開來,這樣作它打亂了我們代碼順序執(zhí)行的流程。如果這個(gè)方法是同步的就好了

本篇文章會(huì)介紹針如何將異步API或者接口封裝成同步方法(使用GCD的方式)

方法調(diào)用者希望調(diào)用的是一個(gè)同步返回的方法,而不是以callback形式攜帶返回值的方法。
// 同步方法
- (NSInteger)methodSync {
    __block NSInteger result = 0;
    [self methodAsync:^(NSInteger value) {
        result = value;
    }];
   // 如果result同步返回就好了
    return result;
}

// 異步方法
- (void)methodAsync:(void(^)(NSInteger result))callBack {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"methodAsync 異步開始");
        sleep(2);
        NSLog(@"methodAsync 異步結(jié)束");
        if (callBack) {
            callBack(5);
        }
    });
}

GCD是我們平常開發(fā)中使用頻率最高的多線程方式,對(duì)于處理上述問題當(dāng)然也是不在話下

  • 方式一:使用派發(fā)組dispatch_group

dispatch_group可以很方便的管理多個(gè)派發(fā)任務(wù),并在任務(wù)結(jié)束時(shí)候可以得到回調(diào)通知,或者可以一直阻塞線程直到派發(fā)組內(nèi)的所有派發(fā)任務(wù)都完成

- (NSInteger)methodSync {
    NSLog(@"methodSync 開始");
    __block NSInteger result = 0;
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    [self methodAsync:^(NSInteger value) {
        result = value;
        dispatch_group_leave(group);
    }];
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"methodSync 結(jié)束 result:%ld", (long)result);
    return result;
}
  • 方式二(推薦):使用信號(hào)量dispatch_semaphore

dispatch_semaphore通常是用來多線程執(zhí)行多個(gè)并發(fā)任務(wù)時(shí)通過信號(hào)量的方式對(duì)并發(fā)執(zhí)行數(shù)量的限制。當(dāng)信號(hào)量不夠(=0)的時(shí)候當(dāng)前調(diào)用線程將被阻塞,所以我們可以通過模擬信號(hào)量不夠的情況來阻塞同步方法的返回,直到方法內(nèi)部的異步回調(diào)之后;

- (NSInteger)methodSync {
    NSLog(@"methodSync 開始");
    __block NSInteger result = 0;
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [self methodAsync:^(NSInteger value) {
        result = value;
        dispatch_semaphore_signal(sema);
    }];
   // 這里本來同步方法會(huì)立即返回,但信號(hào)量=0使得線程阻塞
   // 當(dāng)異步方法回調(diào)之后,發(fā)送信號(hào),信號(hào)量變?yōu)?,這里的阻塞將被解除,從而返回正確的結(jié)果
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    NSLog(@"methodSync 結(jié)束 result:%ld", (long)result);
    return result;
}

當(dāng)然是用操作隊(duì)列OperationQueue也是可以實(shí)現(xiàn)這個(gè)需求,但會(huì)更麻煩一些,我認(rèn)為直接使用GCD的方式是最為輕量的,推薦大家在實(shí)踐中使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容