I recently needed a way to perform an unknown number of asynchronous http requests and wait until they were all done before proceeding. dispatch_groups are a neat feature of Grand Central Dispatch (GCD) that made this easy to do.
There are a couple of ways to use dispatch_groups but the basic idea is the same: create a dispatch_group, give it some tasks, and wait for it to finish those tasks.
First, let’s create a group:
dispatch_group_t group = dispatch_group_create();
There are two ways to add tasks to our dispatch_group. You can either call dispatch_group_async with the group, a dispatch_queue and block to run or manually call dispatch_group_enter.
Calling dispatch_group_async looks something like this:
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do stuff on a global background queue here
});
Or you can manage tasks manually by calling dispatch_group_enter and dispatch_group_leave in pairs:
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do stuff on a global background queue here
dispatch_group_leave(group);
});
Using dispatch_group_enter/dispatch_group_leave is handy when you’re using libraries that provide asynchronous operation (e.g. AFNetworking).
The last thing to do is wait for all of the tasks to finish. The preferred way to do this is to use dispatch_group_notify:
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// Do stuff after all tasks are finished
});
dispatch_group_notify is nice because it does not block the thread it’s called from. If you have a reason to block the current thread, use dispatch_group_wait instead:
dispatch_group_wait(group, DISPATCH_TIME_FOREVER); // Do stuff after all tasks are finished
A full example looks like this:
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do stuff on a global background queue here
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do more stuff on a global background queue here
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// Do stuff after all tasks are finished
});
One important note about dispatch objects: If your project’s deployment target is less than 6.0, you need to manage memory with dispatch_retain and dispatch_release for any dispatch objects you create (groups, queues, semaphores). ARC takes care of managing memory for dispatch objects when your deployment target is 6.0+ (10.8+ for OS X).
sudo apt-get install gcc g++ build-essential libssl-dev libreadline5-dev zlib1g libyaml-dev zlib1g-dev linux-headers-generic libsqlite3-devtar -xvzf ruby-1.9.3-p194.tar.gzcd ruby-1.9.3-p194/ && ./configure —prefix=/usr/local && make && sudo make install
Posted via email from amro’s blog | Comment »
Uh oh. The boy just Climbed out of his crib for the first time.
//Start at negative kWiggleAnimationAngle so we animate to positive kWiggleAnimationAngleview.layer.transform = CATransform3DMakeRotation(-kWiggleAnimationAngle, 0, 0, 1.0);//Setup a transform that will rotate our view to positive kWiggleAnimationAngleCATransform3D transform = CATransform3DMakeRotation(kWiggleAnimationAngle, 0, 0, 1.0);//Setup our animation with the transformCABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@”transform”];animation.toValue = [NSValue valueWithCATransform3D:transform];animation.repeatCount = HUGE_VALF;animation.duration = 0.1;animation.autoreverses = YES;[view.layer addAnimation:animation forKey:@”wiggle”];
//Remove the animation from our view[view.layer removeAnimationForKey:@”wiggle”];//Rotate the view back to its default positionview.layer.transform = CATransform3DMakeRotation(0.0, 0, 0, 1.0);
Posted via email from amro’s blog | Comment »
The case for a real ‘Apple TV’? (Taken with instagram)
Little man wearing his Star Wars shirt. 16 months old today. (Taken with instagram)
Watching Buzz Aldrin speak. Last WWDC session. (Taken with instagram)