假設你的應用在啟動時必須向服務端進行一連串的請求.這些請求可能是獲取配置信息.舉個例子,當你的應用啟動時可能會向服務端請求一些配置信息.這個配置信息可能需要多個請求組合而成.
你想通過調(diào)用一個方法去啟動這些請求,然后全部請求完成后,在一個completion block里面完成你的業(yè)務邏輯. 但是這些請求相互間沒有什么聯(lián)系,我們應該如何做呢? 常見的方式是使用調(diào)度組( dispatch group )來實現(xiàn).
初始化一個dispatch group
dispatch_group_t serviceGroup = dispatch_group_create();
向dispatch group中添加任務
1. 是在這個dispatch group中添加你的代碼塊,然后這些代碼塊會運行在你指定的queue中.
dispatch_group_async(serviceGroup,queue,^{
// some work here
});
通過這樣的方式我們可以:請求之后可以馬上返回我們想要的數(shù)據(jù)职员,然后每個請求中都有自己的completion block殉了。因為,當我們的“任務”完成的時候亡驰,dispatch group 會馬上收到消息通知。
2. 手動告訴dispatch group你要開始某個任務了.完成任務之后,你也需要手動退出dispath group.
通過dispatch_group_enter(),dispatch_group_leave()
兩個方法可以實現(xiàn)進入,退出兩個動作:
dispatch_group_enter(serviceGroup);
[configService startWithCompletion:^(ConfigResponse *results, NSError* error){
// Do something with the error or results
dispatch_group_leave(serviceGroup);
}];
每個enter都必須有相應的leave,否則,你的dispatch group永遠不會結束.在你要去請求一個web service的時候,你先enter dispatch group,然后在返回的completion block中 leave.
下面舉例說明dispatch_group 如何處理多個任務
-(void)fetchConfigurationWithCompletion:(void (^)(NSError* error))completion
{
// Define errors to be processed when everything is complete.
// One error per service; in this example we'll have two
__block NSError *configError = nil;
__block NSError *preferenceError = nil;
// Create the dispatch group
dispatch_group_t serviceGroup = dispatch_group_create();
// Start the first service
dispatch_group_enter(serviceGroup);
[self.configService startWithCompletion:^(ConfigResponse *results, NSError* error){
// Do something with the results
configError = error;
dispatch_group_leave(serviceGroup);
}];
// Start the second service
dispatch_group_enter(serviceGroup);
[self.preferenceService startWithCompletion:^(PreferenceResponse *results, NSError* error){
// Do something with the results
preferenceError = error;
dispatch_group_leave(serviceGroup);
}];
dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{
// Assess any errors
NSError *overallError = nil;
if (configError || preferenceError)
{
// Either make a new error or assign one of them to the overall error
overallError = configError ?: preferenceError;
}
// Now call the final completion block
completion(overallError);
});
}