Blocks & iOS: Introduction to Grand Central Dispatch

Grand Central Dispatch, or GCD, is an extremely important feature introduced in iOS 4.0, OS X 10.6 and later versions. It’s used to distribute the computation across multiple cores dispatching any number of threads needed and  it is optimized to work with devices with multi-core processors.

When using GCD, you don’t need to handle any multiple threads your self. GCD technology will take care of that for you, so you can get to focus on the task itself. GCD works with blocks, which are blocks of code that you need to execute in the background, in low, default or high priority queue, in a serial or concurrent order.

Using GCD in your application will bring a great benefit of all the features mentioned above without the hassle of managing the threads yourself and knowing that the GCD technology will be utilizing multi-core processors found in iOS devices today. Before we dig into GCD itself we’ll need to be comfortable using blocks.

Blocks are a C-level syntactic and runtime feature that let you pass a function as an argument, store it, or execute it on multiple threads. Blocks look very similar to functions, instead of the name of the function replace it with ^ and you’re good to go.

To learn more about blocks visit:

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html

So you can use a block for example as an argument in a method like:


– (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block

where the block parameter is expecting an object, idx and bool pointer.

Here is one example of how to use a block for enumerating on an array:


NSArray *inputArray = [NSArray arrayWithObjects:@”1″,@”2″,@”3″,@”4″,[NSObject new],@”a”,@”b”, nil];

[inputArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){

if (![obj isKindOfClass:[NSString class]]) {

NSLog(@”found the first different Object: %@”,obj);

*stop = YES;

}

else {

NSLog(@”%@ at index:%d”, obj, idx);

}

return;

}];


So the output will be:


1 at index:0

2 at index:1

3 at index:2

4 at index:3

found the first different Object:


So now that we know more about blocks, I’ll show you how you can add them to a serial queue. Adding blocks to a serial queues ensures that these blocks of code will be executed one after the other. If one block is taking too long, the rest of the blocks will have to wait until its done. Serial blocks are useful in many cases where ensuring the order of execution is critical.

So our block will have some definitions like:


static void (^counterBlock)(int,char, NSUInteger , GCDMaster*) = ^(int count, char letter, NSUInteger blockNumber, GCDMaster *delegate){

… block does some work here

}


So this block is named counterBlock and it taks arguments: chat, NSUInteger and an object typed GCDMaster. So the arguments in this block are passed in from the method calling the block. As you have seen earlier, you can specify any configuration of a block just like you would do with functions.

Now lets talk about Dispatch Queues. Apple’s definition of Dispatch Queues is:

Dispatch queues are a C-based mechanism for executing custom tasks. A dispatch queue executes tasks either serially or concurrently but always in a first-in, first-out order. (In other words, a dispatch queue always dequeues and starts tasks in the same order in which they were added to the queue.) A serial dispatch queue runs only one task at a time, waiting until that task is complete before dequeuing and starting a new one. By contrast, a concurrent dispatch queue starts as many tasks as it can without waiting for already started tasks to finish.

So we want to dispatch a few of these blocks on our serial Queue. Let’s start by creating a serial queue:


serialQueue = dispatch_queue_create(“com.3Pillar.SerialQueue”, NULL);


This will define a serial queue with a reverse domain name so we can identify our queues. Next we will add 4 of these blocks with different arguments to run serially on the queue:


dispatch_async(serialQueue, ^{counterBlock(20000 ,’a’ ,0, self);});dispatch_async(serialQueue, ^{counterBlock(1000  ,’A’ ,1 ,self);});dispatch_async(serialQueue, ^{counterBlock(20000 ,’0′ ,2 ,self);});dispatch_async(serialQueue, ^{counterBlock(2000  ,’Z’ ,3 ,self);});

What we did now is we added 4 blocks to our queue “serialQueue” with various different arguments. These blocks will be executed one after the other. When block 1 is finished 2 is started and so forth. So if we have a log message when the block start and end it will look like this:


==block 1 started ==

==block 1 ended ==

==block 2 started ==

==block 2 ended ==

==block 3 started ==


But if we would want to execute the blocks concurrently and we don’t have the need to run them sequentially then we’ll need to create a concurrent queue. Apple provides you with a number of concurrent queues that you can access from you’re application. These queues are global and they have 3 priorities DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_PRIORITY_DEFAULT and DISPATCH_QUEUE_PRIORITY_LOW priority.

To get a concurrent queue:


dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);


Then we add the blocks to the queue the same way as before:


dispatch_async(concurrentQueue, ^{counterBlock(20000 ,’a’ ,0, self);});dispatch_async(concurrentQueue, ^{counterBlock(1000  ,’A’ ,1 ,self);});

dispatch_async(concurrentQueue, ^{counterBlock(20000 ,’0′ ,2 ,self);});

 

dispatch_async(concurrentQueue, ^{counterBlock(2000  ,’Z’ ,3 ,self);});

 


GCD runs these blocks concurrently, there is no way to expect which one executes first.

So the output would be random like this:


==block 2 started ==

==block 3 started ==

==block 3 ended ==

==block 1 started ==


Once the Queue is running you can suspend it and resume it by calling the appropriate methods dispatch_suspend and dispatch_resume. Note that the calls to dispatch_suspend and dispatch_resume must be balanced. Please feel free to run the attached project with all the example given in this blog for you’re self and feel free to experiment with GCD and make you’re self familiar with it.

Once you start getting comfortable working with blocks and using queues you will be able to introduce many performance improvements to your code and send heavy operations back to a GCD queue while freeing your UI to move freely and keep the user experience smooth.

 

This post was also published on Eddie’s personal blog, which can be accessed here: http://objective-coder.blogspot.com/2012/12/introduction-to-grand-central-dispatch.html

Eddie Ishaq

Eddie Ishaq

Senior Software Engineer & iOS Competency Center Lead

Edward “Eddie” Ishaq is a Senior Software Engineer at 3Pillar Global and the head of our iOS Competency Center. Eddie has a passion for designing and developing custom apps from the ground up. At 3Pillar, he was worked primarily on a custom iPad app that 3Pillar created for a defense contractor as a proof-of-concept fleet maintenance tool. He has spent more than 10 years working in the software industry, and his specialties in addition to developing iPad apps include working with continuous integration, designing projects, optimizing web servers, PHP, MySQL, Ajax, JQuery, and CSS.

9 Responses to “Blocks & iOS: Introduction to Grand Central Dispatch”
  1. Satish on

    Excellent article..thank you..

    Reply
  2. vikash kumar on

    Really great explanation.., i solve my all doubt regarding serial and concurrent queue.
    Thanx a lot

    Reply
  3. jp on

    Great Work, Got good understanding!

    Reply
  4. vainAku on

    Simple and best!

    Reply
  5. vainAku on

    Hi, I cannot find the ink to the sample project containing the examples.

    Reply
  6. Andrei on

    Excellent article.
    But there is an issue
    [inputArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) in

    In this line
    BOOL can not be *

    Reply
  7. Balachandran on

    Crisp and clear. For someone who are not familiar with the term GCD, this article is the best to begin with.

    Reply
  8. Abhinav on

    Great Article
    Very Useful Thanks.

    Reply
  9. Ravi Chandra Reddy M on

    Excellent article..thank you very much. I got the some clarity on GCD

    Reply
Leave a Reply

Related Posts

Designing the Future & the Future of Work – The I... Martin Wezowski, Chief Designer and Futurist at SAP, shares his thoughts on designing the future and the future of work on this episode of The Innovat...
The 4 Characteristics of a Healthy Digital Product Team Several weeks ago, I found myself engaged in two separate, yet eerily similar, conversations with CEOs struggling to gain the confidence they needed t...
Recapping Fortune Brainstorm Tech – The Innovation Eng... On this episode of The Innovation Engine, David DeWolf and Jonathan Rivers join us to share an overview of all the news that was fit to print at this ...
4 Reasons Everyone is Wrong About Blockchain: Your Guide to ... You know a technology has officially jumped the shark when iced tea companies decide they want in on the action. In case you missed that one, Long Isl...
The Connection Between Innovation & Story On this episode of The Innovation Engine, we'll be looking at the connection between story and innovation. Among the topics we'll cover are why story ...