Quick introduction to Grand Central Dispatch and why you should use it

Hello idevs! Time sure flew by lately, so here I am, once more having to post one of my development adventures, forced by the unwritten agreement I took when joining the iDevBlogADay project.

As any programmer can tell you, in most (over 95%) of your programming tasks you won’t have to deal with threads or any form of asynchronous programming. Chances are you will never need to deal with this, in most programming jobs. However, in iOS world, you have to. And unless people scare you upfront by pushing big words like threads and asynchronous programming, you should totally spend 5 minutes to at least grasp the big picture.

I don’t have time to get into details(and I also don’t feel like it), so I’ll just cut to the chase and talk non-programming for a second: whenever you do something that relates to the network, with opening up big files or other time-expensive operations, you risk freezing your app for longer than you’d wish. People will notice, get angry, quit the app, leave bad reviews, which will in turn bankrupt you. You don’t want this.

The good news is that Apple gave you several ways to handle this kind of situations in many ways, depending on your needs.

In 99% of the situations I needed this kind of non-blocking behavior, I handled them by just calling [self performSelectorInBackground:@selector(mybackgroundMethod) withObject:nil]. performSelectorInBackground can be found in NSObject, so all your objects and classes will have it by default. It’s pretty straightforward and was good enough to keep me company for the past 3 years.

The downside to performSelectorInBackground is that it’s pretty slow(it creates a NSThread object dynamically, etc); also, passing data to the method you want to keep in background it is a pain, as you hav to wrap it up in the withObject parameter, or as a global in your object. Calling back methods on your main thread was also convoluted, involving calls to “performSelectorOnMainThread:withObject:waitUntilDone:“. Not exactly straightforward.

Enter Grand Central Dispatch. It’s a new technology added by Apple in the past years, and you really should take a look at it. It might look pretty scary at first look, but perhaps I’ll be of help. If not, this wikipedia article is also a good start for the beginners.

What is GCD? It’s a technology that Apple made that works like threads but way more optimized, and also takes advantage of the multiple cores in your processor, so it will make your app faster. GCD works with “dispatch queues” instead of threads. You create (or use the default ones) queues in which you push fragments of code. If you push these fragments using “dispatch_sync”, these blocks of code will run sequentially just like normal code does. However, when you call “dispatch_async”, they start behaving like threads – won’t block your app, and possibly be called in the background on your iPhone 4S second core.

For the bare minimum basic functionality, you need to do as little as:

  1. put your possibly time consuming code in

dispatch_async(dispatch_get_global_queue(0, 0), ^{<br /> .... // your code here<br /> });<br />

  1. when you need to do something to the view, you will need to surround your code by

dispatch_async(dispatch_get_main_queue(), ^{<br /> ....// your code here<br /> });<br />
You will notice that this actually looks a lot like defining a method with your possibly time consuming code and call that method by passing it as an argument to performSelectorInBackground. Similarly, when you wanted to have some code called on the main thread you’d put it in its own method which you’d call with perform..onMainThread… The same idea, really, only that GCD is cleaner code (no more defining methods for background/foreground stuff – you just use blocks), you type less and it’s faster, especially for multiple threads(queues).

Once again, slower this time: at the bare minimum, you have to deal with two built-in queues: the one returned by calling dispatch_get_global_queue(0, 0) which is a default background one, and dispatch_get_main_queue(), which is your main program queue. You can also create your own custom queues and give them nice names, which makes it easier to debug or follow in your app’s logs.

Here’s a hopefully better sample:

-(void)letMeShowYouASampleOfGCD{<br /> int precision = 50;<br /> dispatch_async(dispatch_get_global_queue(0, 0), ^{<br /> //here i do whatever I want do do,<br /> //such as computing the 100th digit of PI*e,<br /> //or checking out if I can download an internet resource.<br /> precision = precision + 50; // just to show how easy it is to send data to blocks<br /> [self computePiTimesEWithPrecision:precision];<br /> });<br /> }

You notice that you call the code by writing it in a block, which is also nothing scary; it’s just some code surrounded by ^{} and possibly some parameters. I’ll write about them some other time, if you wish. The nice things about blocks is that they basically behave like methods, but you have less to worry about sending data to them. They “see” surrounding variables and can read them. Obviously instead of simply calling computePiTimesEWithPrecision I could have written the code directly there. But you understand that it was just an example.

Now, the other thing to remember about GCD is that what you compute in a background queue happens in the background. In order to update your main view (let’s say by setting the text value of a UILabel), you need to call once more dispatch_async, this time on the main queue.
Like this:

-(void) computePiTimesEWithPrecision:(int)precision{<br /> // I do my computation, nothing special here<br /> // result = ...;<br /> dispatch_async(dispatch_get_main_queue(), ^{<br /> [myResult setText:[NSString stringWithFormat:@"%@", result]];<br /> });<br /> }<br />
So that’s about it. The extremely basic introduction to GCD. I hope it wasn’t too confusing and provided you with enough info to start playing with GCD by yourself or to start learning more from wikipedia or apple’s docs.