GCD group 的使用

group 頭文件中函數(shù)的解析:


/*
OS_OBJECT_DECL(dispatch_object);
#define DISPATCH_DECL(name)  OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)
*/
// 從上面可以看出  dispatch_group 是  dispatch_object 子類
DISPATCH_DECL(dispatch_group);

dispatch_group_t ==  DISPATCH_DECL(dispatch_group);


/*
 創(chuàng)建一個(gè)組滩愁, 創(chuàng)建的組可能與 block 相關(guān)聯(lián)。
 這個(gè)調(diào)度組能夠被用來(lái)等待他引用的 block 的完成秕磷。
  - result : 一個(gè)新的組涵妥。 在失敗的情況下返回 NULL
*/
dispatch_group_t
dispatch_group_create(void);


/**
調(diào)度組 在 queue 異步執(zhí)行 block
*/
void
dispatch_group_async(
    dispatch_group_t group,            // 調(diào)度組對(duì)象
    dispatch_queue_t queue,            // 隊(duì)列
    dispatch_block_t block             // block
);           

/**
調(diào)度組 在 queue 異步執(zhí)行 函數(shù)
*/
void
dispatch_group_async_f(
    dispatch_group_t     group,          // 調(diào)度組對(duì)象
    dispatch_queue_t     queue,          // 隊(duì)列
    void                 *context,       // 上下文(傳遞給函數(shù)的)
    dispatch_function_t  work            // 函數(shù)
);


long
dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);

// 組中異步執(zhí)行任務(wù)全部執(zhí)行完成的通知
void
dispatch_group_notify(
    dispatch_group_t group,       // 隊(duì)列組
    dispatch_queue_t queue,       // 執(zhí)行任務(wù)的隊(duì)列
    dispatch_block_t block);      // 任務(wù) 


// 組中異步執(zhí)行的函數(shù)全部執(zhí)行的通知
void
dispatch_group_notify_f(
    dispatch_group_t group,                  // 隊(duì)列組
    dispatch_queue_t queue,                  // 執(zhí)行任務(wù)的隊(duì)列   
    void *context,                           // 上下文
    dispatch_function_t work);               // 函數(shù)

// 入組函數(shù)
void
dispatch_group_enter(dispatch_group_t group);

// 出組函數(shù)
void
dispatch_group_leave(dispatch_group_t group);

調(diào)度組在項(xiàng)目中的使用(調(diào)度組的基本使用)

調(diào)度組:
調(diào)度組是用來(lái)協(xié)調(diào)一個(gè)或多個(gè)任務(wù)提交到隊(duì)列異步觸發(fā)的。 應(yīng)用程序可以使用調(diào)度組等待所有調(diào)度組中的所有任務(wù)的完成。

所有異步隊(duì)列執(zhí)行完畢后得到一個(gè)通知覆旭。
**場(chǎng)景: **
a 異步下載任務(wù)退子,b 異步下載任務(wù), c 異步下載任務(wù)型将。
只有在 a寂祥, b, c 三個(gè)異步下載任務(wù)全部完成的情況下七兜。才通知主線程刷新界面丸凭。亦可以通知某個(gè)隊(duì)列執(zhí)行其他的操作。

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

// 創(chuàng)建一個(gè)組 (獲得一個(gè)新的腕铸,空的調(diào)度組)
dispatch_group_t g =  dispatch_group_create();

// 將隊(duì)列關(guān)聯(lián)組
dispatch_group_async(g, dispatch_get_global_queue(0, 0), ^{
    NSLog(@"taskA: %@", [NSThread currentThread]);
});

// 將隊(duì)列關(guān)聯(lián)組
dispatch_group_async(g, dispatch_get_global_queue(0, 0), ^{
    NSLog(@"taskB: %@", [NSThread currentThread]);
});

// 將隊(duì)列關(guān)聯(lián)組
dispatch_group_async(g, dispatch_get_global_queue(0, 0), ^{
    NSLog(@"taskC: %@", [NSThread currentThread]);
});

// 組中的隊(duì)列全部執(zhí)行完畢后就通知調(diào)度組
dispatch_group_notify(g, dispatch_get_main_queue(), ^{
    NSLog(@"MainTask: %@", [NSThread currentThread]);
});


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


// 打印結(jié)果
2016-06-23 09:12:05.162 Thread-Objc[9371:984276] before: <NSThread: 0x7f8c437028a0>{number = 1, name = main}
2016-06-23 09:12:05.163 Thread-Objc[9371:984276] after: <NSThread: 0x7f8c437028a0>{number = 1, name = main}
2016-06-23 09:12:05.163 Thread-Objc[9371:984320] taskA: <NSThread: 0x7f8c43712610>{number = 2, name = (null)}
2016-06-23 09:12:05.163 Thread-Objc[9371:984328] taskC: <NSThread: 0x7f8c43500a80>{number = 4, name = (null)}
2016-06-23 09:12:05.163 Thread-Objc[9371:984323] taskB: <NSThread: 0x7f8c4376ada0>{number = 3, name = (null)}
2016-06-23 09:12:05.167 Thread-Objc[9371:984276] MainTask: <NSThread: 0x7f8c437028a0>{number = 1, name = main}

上面的代碼是一個(gè)簡(jiǎn)單的使用方式惜犀。

調(diào)度組的使用的原理解析
打開終端輸入

// 使用這個(gè)命令可以查看 GCD 的詳細(xì)文檔
$ man dispatch

// 查看和 group 相關(guān)的文檔
$ man dispatch_group_create

文檔示例
(官方文檔的說(shuō)明)

// dispatch_group_async() 函數(shù)的操作和下面是等價(jià)的:
The dispatch_group_async() convenience function behaves like so:

void
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispat
ch_block_t block)
{
             // 引用計(jì)數(shù)器加1
             dispatch_retain(group);

            // 入組
             dispatch_group_enter(group);

            // 任務(wù)異步執(zhí)行
             dispatch_async(queue, ^{

                      // 執(zhí)行任務(wù)
                     block();

                     // 出組(通知組,任務(wù)執(zhí)行完畢)
                     dispatch_group_leave(group);
                     
                     // 引用計(jì)數(shù)器減1 
                     dispatch_release(group);
        });
}

示例代碼改寫

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

dispatch_group_t g =  dispatch_group_create();


dispatch_group_enter(g);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    NSLog(@"taskA: %@", [NSThread currentThread]);
    
    dispatch_group_leave(g);
});



dispatch_group_enter(g);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    NSLog(@"taskB: %@", [NSThread currentThread]);
    
    dispatch_group_leave(g);
});



dispatch_group_enter(g);

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    NSLog(@"taskC: %@", [NSThread currentThread]);
    
    dispatch_group_leave(g);
});


dispatch_group_notify(g, dispatch_get_main_queue(), ^{
    NSLog(@"MainTask: %@", [NSThread currentThread]);
});


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

// 打印結(jié)果
2016-06-23 09:35:52.744 Thread-Objc[9540:1004789] before: <NSThread: 0x7fdec3d04920>{number = 1, name = main}
2016-06-23 09:35:52.744 Thread-Objc[9540:1004789] after: <NSThread: 0x7fdec3d04920>{number = 1, name = main}
2016-06-23 09:35:52.745 Thread-Objc[9540:1004833] taskA: <NSThread: 0x7fdec3d11d30>{number = 2, name = (null)}
2016-06-23 09:35:52.745 Thread-Objc[9540:1004829] taskC: <NSThread: 0x7fdec3c09fa0>{number = 3, name = (null)}
2016-06-23 09:35:52.745 Thread-Objc[9540:1004822] taskB: <NSThread: 0x7fdec3d09a50>{number = 4, name = (null)}
2016-06-23 09:35:52.749 Thread-Objc[9540:1004789] MainTask: <NSThread: 0x7fdec3d04920>{number = 1, name = main}


/*
 dispatch_group_enter(g); 操作都在 g 所在線程狠裹。 
 即當(dāng)前線程虽界, 在進(jìn)行異步操作之前, dispatch_group_enter(g) 都已經(jīng)全部執(zhí)行完畢涛菠。

 g 中已經(jīng)完整的記錄了 block 的個(gè)數(shù)莉御。

 追蹤 NSLog(@"after: %@", [NSThread currentThread]); 的打印可以知道。
 
 執(zhí)行一次 dispatch_group_enter(g) 操作俗冻,block 在組中的記錄就會(huì) 加 1 颈将。
 在子線程中執(zhí)行一次 dispatch_group_leave(g); 會(huì)使 block 在組中的記錄就會(huì) 減 1 。
 
 當(dāng)組中的 block 記錄的值為 0 的時(shí)候言疗,就會(huì)調(diào)用 dispatch_group_notify() 函數(shù)晴圾。
 
 */



理解上面的實(shí)例后,對(duì)于 GCD 中的組基本的學(xué)習(xí)已經(jīng)差不多了


細(xì)節(jié)知識(shí)點(diǎn)說(shuō)明:

dispatch_group_enter();dispatch_group_leave(); 必須成對(duì)使用噪奄。 這兩個(gè)函數(shù)會(huì)更新 block 在組中的數(shù)量死姚。

在這個(gè)示例中除了 dispatch_group_waitdispatch_group_async_f 基本都用了一遍。
dispatch_group_async_f 是函數(shù)調(diào)用的基本不用勤篮。

  • **dispatch_group_wait :
    ** 意思是等待 group 中所有的 block 都執(zhí)行完畢觸發(fā)這個(gè)函數(shù)都毒,或者等待指定的時(shí)間完成后觸發(fā)這個(gè)函數(shù)。這個(gè)指定的時(shí)間內(nèi)group 變?yōu)榭张龅蓿@個(gè)函數(shù)將返回一個(gè) 0 账劲,表示成功。否則就是一個(gè)非空的值金抡。當(dāng)參數(shù)的值為 DISPATCH_TIME_FOREVER 的時(shí)候瀑焦, 返回值總為空。
    注意:
    • 只有在所有的任務(wù)都添加到隊(duì)列 才建議調(diào)用 dispatch_group_wait () 函數(shù)梗肝,如果后續(xù)還有新的 block 添加到 組中榛瓮,請(qǐng)使用新的組。 ( 這個(gè)dispatch_group_wait () 還是必須在最后調(diào)用)
    • 只有在所有的任務(wù)都添加到隊(duì)列 才建議調(diào)用 dispath_group_notify() 函數(shù)巫击,如果后續(xù)還有新的 block 添加到 組中禀晓,請(qǐng)使用新的組精续。 ( 這個(gè)dispath_group_notify() 還是必須在最后調(diào)用)
  • dispatch_group_wait() 和 dispath_group_notify() 的 選擇:
    dispatch_group_wait (DISPATCH_TIME_FOREVER) == dispath_group_notify()
    AFN 中的網(wǎng)絡(luò)請(qǐng)求超時(shí)就是使用 dispatch_group_wait () 實(shí)現(xiàn)的。 當(dāng)一個(gè)時(shí)間結(jié)束后自動(dòng)返回一個(gè)超時(shí)錯(cuò)誤粹懒。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末重付,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凫乖,更是在濱河造成了極大的恐慌堪夭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拣凹,死亡現(xiàn)場(chǎng)離奇詭異森爽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嚣镜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門爬迟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人菊匿,你說(shuō)我怎么就攤上這事付呕。” “怎么了跌捆?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵徽职,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我佩厚,道長(zhǎng)姆钉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任抄瓦,我火速辦了婚禮潮瓶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钙姊。我一直安慰自己毯辅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布煞额。 她就那樣靜靜地躺著思恐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膊毁。 梳的紋絲不亂的頭發(fā)上胀莹,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音媚媒,去河邊找鬼嗜逻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缭召,可吹牛的內(nèi)容都是我干的栈顷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼嵌巷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼萄凤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起搪哪,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤靡努,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后晓折,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惑朦,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年漓概,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漾月。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胃珍,死狀恐怖梁肿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情觅彰,我是刑警寧澤吩蔑,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站填抬,受9級(jí)特大地震影響烛芬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜飒责,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一蛀骇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧读拆,春花似錦擅憔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至辟灰,卻和暖如春个榕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芥喇。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工西采, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人继控。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓械馆,卻偏偏與公主長(zhǎng)得像胖眷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霹崎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • 背景 擔(dān)心了兩周的我終于輪到去醫(yī)院做胃鏡檢查了珊搀!去的時(shí)候我都想好了最壞的可能(胃癌),之前在網(wǎng)上查的癥狀都很相似尾菇。...
    Dely閱讀 9,229評(píng)論 21 42
  • 3.GCD GCD的全稱是Grand Central Dispatch,提供了非常多的純C語(yǔ)言的函數(shù) GCD的優(yōu)勢(shì)...
    Mario_ZJ閱讀 476評(píng)論 0 0
  • GCD調(diào)度隊(duì)列是執(zhí)行任務(wù)的強(qiáng)大工具境析。調(diào)度隊(duì)列允許您相對(duì)于調(diào)度者異步或者同步的執(zhí)行任意代碼塊。您能夠使用調(diào)度隊(duì)列來(lái)執(zhí)...
    坤坤同學(xué)閱讀 6,668評(píng)論 1 3
  • GCD (Grand Central Dispatch) :iOS4 開始引入派诬,使用更加方便劳淆,程序員只需要將任務(wù)添...
    池鵬程閱讀 1,326評(píng)論 0 2
  • 由于目前針對(duì)Swift字典轉(zhuǎn)模型沒(méi)有什么好的第三方沛鸵,所以需要自己解析模型數(shù)據(jù)。模型解析數(shù)據(jù)中可以充分使用模型屬性的...
    ZhengYaWei閱讀 2,120評(píng)論 1 0