dispatch group
有時候我們會有這種需求,在剛進去一個頁面需要發(fā)送兩個請求饮怯,并且某種特定操作必須在兩個請求都結(jié)束(成功或失敗)的時候才會執(zhí)行嚎研,最low的辦法第二個請求嵌套在第一個請求結(jié)果后在發(fā)送蓖墅,在第二個請求結(jié)束后再執(zhí)行操作。還有就是只使用一個Serial
Dispatch Queue临扮,把想要執(zhí)行的操作全部追加到這個Serial Dispatch
Queue中并在最后追加某種特定操作论矾,頗為復雜操作。但是呢杆勇,我們這里介紹更高級的辦法使用dispatch group贪壳。
我們將ABC三個任務block追加到Global Dispatch Queue,ABC全部執(zhí)行完蚜退,會執(zhí)行dispatch_group_notify中的block闰靴。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t ?group = dispatch_group_creat();
dispatch_group_async(group,queue钻注,^{執(zhí)行任務A});
dispatch_group_async(group蚂且,queue,^{執(zhí)行任務B});
dispatch_group_async(group幅恋,queue杏死,^{執(zhí)行任務C});
dispatch_group_notify(group,dispatch_get_main_queue(),^{執(zhí)行最終的特定操作});
ABC的執(zhí)行順序不固定,因為是Global Dispatch Queue即Concurrent Dispatch Queue多個現(xiàn)場并行執(zhí)行。
上面的dispatch_group_notify(group,dispatch_get_main_queue(),^{執(zhí)行最終的特定操作});操作還可以更改為
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
dispatch_group_wait第二個參數(shù)指定為等待的時間(超時)淑翼,屬于dispatch_time_t類型腐巢,在這里使用DISPATCH_TIME_FOREVER,意味著永久等待窒舟。如果dispatch group的處理尚未結(jié)束系忙,就會一直等待诵盼。
如果指定等待時間為1秒如下:
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NESC_PER_SEC)惠豺;
long result = dispatch_group_wait(group,time);
if(result == 0) { dispatch group的全部處理執(zhí)行結(jié)束}
else { dispatch groupe的某一處理還在執(zhí)行中};
但是呢上面這種dispatch_group的排列執(zhí)行方式,是不會考慮block塊內(nèi)部的異步請求情況的风宁,它只能保證把block內(nèi)的非異步直觀代碼執(zhí)行完洁墙,所以如果ABC三個任務中如果有執(zhí)行異步的請求,那么在dispatch_group_notify最終任務執(zhí)行中戒财,那個異步請求不一定毀掉結(jié)束热监。
在這里給大家介紹針對這種問題另一個API。
dispatch_group_enter/dispatch_group_leave
dispatch_group_t group = disoatch_group_creat();
dispatch_group_enter(group);
dispatch_async(dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//在這里執(zhí)行異步請求A
并且在執(zhí)行結(jié)束代碼(成功或失敗)中寫上dispatch_group_leave(group);
});
dispatch_async(dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//在這里執(zhí)行異步請求B
并且在執(zhí)行結(jié)束代碼(成功或失敗)中寫上dispatch_group_leave(group);
});
dispatch_group_notify(group,dispatch_get_main_queue(),^{執(zhí)行最終的特定操作});
上面這種做法當執(zhí)行到dispatch_group_notify饮寞,一定是AB兩個異步請求都加在結(jié)束了孝扛。dispatch_group_enter(group)和dispatch_group_leave(group);必須成對出現(xiàn),編譯器會強制識別當出現(xiàn)dispatch_group_leave全部結(jié)束才執(zhí)行dispatch_group_notify幽崩,即使這種苦始,檔異步執(zhí)行了AB兩個請求,也不能保證請求執(zhí)行結(jié)束的先后順序慌申,如果任務B的請求參數(shù)包含請求A的返回參數(shù)陌选,那么只能用最Low的辦法將請求B嵌套在A中執(zhí)行,當然如果你有更好的辦法歡迎提出來哈蹄溉。
最近的項目正好有多個請求并發(fā)執(zhí)行咨油,但需要返回所有請求的結(jié)果之后,再更新界面的需求柒爵,正好用到dispatch group役电,還比較滿足需求,但是碰到任務B的請求參數(shù)包含請求A的返回參數(shù)這種情況也有可能棉胀,還真是需要找一個優(yōu)雅的姿勢解決這種情況宴霸。
轉(zhuǎn)自:http://www.cocoachina.com/ios/20160804/17291.html