Skip to content

Instantly share code, notes, and snippets.

@benzamin
Last active January 29, 2017 09:21
Embed
What would you like to do?
Using dispatch_group to execute code synchronously, this sample singletone class might help to implement it easily.
#import <Foundation/Foundation.h>
@interface DispatchGroupManager : NSObject
{
}
/**
* Singleton constructor
* @return Singleton instance of DispatchGroup.
*/
+(instancetype)sharedManager;
/*
* Initiate a group of of tasks. Once all tasks are finished, a completion block will execute
*/
-(void)initGroupTasksWithName:(NSString*)groupName;
/**
* Supply a completion block once all the async tasks are finished
* @param the completion block to execute once all the group tasks are done.
*/
-(void)addGroupTasksCompletion:(void(^)())completion forGroup:(NSString*)groupName;
/**
* Should be called when a async task in about to be added in taskGroup
*/
-(void)addFollowingTaskToGroup:(NSString*)groupName;
/**
* Should be called when a async task in done in taskGroup
*/
-(void)doneThisTaskInGroup:(NSString*)groupName;
@end
#import "DispatchGroupManager.h"
@interface DispatchGroupManager()
@property (strong, readwrite, nonatomic) NSMutableDictionary *asyncTasksGroupDic;
@end
@implementation DispatchGroupManager
#pragma mark - Shared Manager Initialization
+ (instancetype)sharedManager
{
static dispatch_once_t pred;
static DispatchGroupManager *DispatchGroupManager = nil;
dispatch_once(&pred, ^{
sharedInstance = [[DispatchGroupManager alloc] init];
});
return sharedInstance;
}
#pragma mark - Group task methods
-(void)initGroupTasksWithName:(NSString*)groupName
{
if(!groupName)
return;
if(!self.asyncTasksGroupDic)
self.asyncTasksGroupDic = [[NSMutableDictionary alloc] init];
dispatch_group_t oldDispatchGroup = [self.asyncTasksGroupDic objectForKey:groupName];
if(oldDispatchGroup){
[self.asyncTasksGroupDic removeObjectForKey:groupName];
}
dispatch_group_t dispatchGroup = dispatch_group_create();
[self.asyncTasksGroupDic setObject:dispatchGroup forKey:groupName];
}
-(void)addGroupTasksCompletion:(void(^)())completion forGroup:(NSString*)groupName
{
if(!groupName)
return;
dispatch_group_t dispatchGroup = [self.asyncTasksGroupDic objectForKey:groupName];
if(dispatchGroup){
dispatch_group_notify(dispatchGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
if(completion){
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
}
});
}
}
-(void)addFollowingTaskToGroup:(NSString*)groupName
{
if(!groupName)
return;
dispatch_group_t dispatchGroup = [self.asyncTasksGroupDic objectForKey:groupName];
if(dispatchGroup){
dispatch_group_enter(dispatchGroup);
}
}
-(void)doneThisTaskInGroup:(NSString*)groupName
{
if(!groupName)
return;
dispatch_group_t dispatchGroup = [self.asyncTasksGroupDic objectForKey:groupName];
if(dispatchGroup){
dispatch_group_leave(dispatchGroup);
}
}
@end
#import "DispatchGroupManager.h"
#define TRAVEL_OVERVIEW_GROUP_TASK @"localTravelOverviewGroupTask"
@implementation MySampleViewController
//.... Other codes .....
//This is a sample method where you need 2 API calls to finish to finally show the result in the tableView
-(void)loadAllTicketsAndHotels
{
__weak typeof(self) weakSelf = self;
//Initiate the group task
[[DispatchGroupManager sharedManager] initGroupTasksWithName:TRAVEL_OVERVIEW_GROUP_TASK];
[self.view addSubview:_loadingView]; // show a loading view while we load everything
//----------- Task 1. get all tickets-------------------
[[DispatchGroupManager sharedManager] addFollowingTaskToGroup:TRAVEL_OVERVIEW_GROUP_TASK];
#warning We'r pulling only first page, but need to fetch all by adding the limit param, i.e "limit=1000"
[TicketsService getAllTicketsForIssueId:self.localTravel.issueIdentifier pageNo:1 completion:^(NSArray *tickets, Pagination *paginationInfo, NSError *error) {
if (!error && weakSelf) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.allTicketsArray addObjectsFromArray:tickets];
}
NSLog(@"Done loading all tickets");
[[DispatchGroupManager sharedManager] doneThisTaskInGroup:TRAVEL_OVERVIEW_GROUP_TASK];
}];
//-------------- Task 2. get all hotels ----------------
[[DispatchGroupManager sharedManager] addFollowingTaskToGroup:TRAVEL_OVERVIEW_GROUP_TASK];
#warning We'r pulling only first page, but need to fetch all by adding the limit param, i.e "limit=1000"
[HotelService getAllHotelsForIssueId:self.localTravel.issueIdentifier pageNo:1 completion:^(NSArray *hotels, Pagination *paginationInfo, NSError *error) {
if (!error && weakSelf) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.allHotelsArray addObjectsFromArray:hotels];
}
NSLog(@"Done loading all Hotels");
[[DispatchGroupManager sharedManager] doneThisTaskInGroup:TRAVEL_OVERVIEW_GROUP_TASK];
}];
//---- This method will add the action we want to take once the 2 API calls are finished
[[DispatchGroupManager sharedManager] addGroupTasksCompletion:^{
if (weakSelf) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.loadingView removeFromSuperview]; //remove the loading view
[strongSelf generateTravelOverview]; //combine the API call results and show it in the view
}
} forGroup:TRAVEL_OVERVIEW_GROUP_TASK];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment