Grand Central Dispatch iOS
Grand Central Dispatch iOS Santiapps.com by Marcio Valenzuela

GCD helps improve your apps performance and responsiveness by outsourcing processes that require a lot or computing power to the background while keeping your UI responsive.  Normally you might want to do some heavy lifting.

Let’s create an Empty Application.  You need to declare a IBOutlet UIImageView *imageView ivar in your appDelegate, make it a property and synthesize it in .m and make the connection in Interface Builder, IB.  In it’s viewDidLoad method put the following code:

// Download the image
NSURL *url = [NSURL URLWithString:@”http://www.santiapps.com/assets/bbkoko.jpg”];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLResponse *res = [[NSURLResponse alloc] init];
NSError *err = nil;
NSData *data = nil;
data = [NSURLConnection sendSynchronousRequest:req
returningResponse:&res
error:&err];
// Convert the data to a UIImage
UIImage *image = [UIImage imageWithData:data];

// Scale the image
UIImage *thumbImage = nil;
CGSize newSize = CGSizeMake(90, (90 / image.size.width) * image.size.height);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
thumbImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Add this to a UIImageView
self.imageView.image = thumbImage;

If you load this up, you’ll notice it’ll take quite some time to load.  Analyzing this code you notice that the heaviest workload is the NSURL request. Ideally we would like to dispatch this to a separate queue so that the app doesn’t stall while this is happening. BTW, the best way to see how a task like this stalls your app’s launch is to place the code right into your applicationDidFinishLaunching, which will stall the display of the MainWindow.xib.

Run the code as is and you’ll notice how the app hangs on the black screen before displaying the default white colored MainWindow.xib background.

So what we want to do is throw this out into a side queue so as to not hold up the presenting of the UI of the app. Grand Central Dispatch, or GCD for short, is ideal for this. First add this line to your AppDelegate, or whatever the class you are using it in:

#import <dispatch/dispatch.h>

Then fix your code to implement GCD:

dispatch_queue_t downloadQueue = dispatch_queue_create(“imageDL”, NULL);
dispatch_async(downloadQueue, ^{

NSURL *url = [NSURL URLWithString:@”http://www.santiapps.com/assets/bbkoko.jpg”];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLResponse *res = [[NSURLResponse alloc] init];
NSError *err = nil;
NSData *data = nil;
data = [NSURLConnection sendSynchronousRequest:req
returningResponse:&res
error:&err];
     dispatch_async(dispatch_get_main_queue(), ^{

// Convert the data to a UIImage
UIImage *image = [UIImage imageWithData:data];

// Scale the image
UIImage *thumbImage = nil;
CGSize newSize = CGSizeMake(90, (90 / image.size.width) * image.size.height);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
thumbImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Add this to a UIImageView
self.imageView.image = thumbImage;

});

});

dispatch_release(downloadQueue);

Run it now and notice how fast the MainWindow.xib pops up on the screen and later displays the image once it has downloaded.

If you want to get a more live view of how GCD works, try this code out in an app:

Simple Block Time Example
           

             NSDate *date = [NSDate date];

void (^now)(void) = ^ {

NSLog(@”The date and time is %@”, date);
};

now();
date = [NSDate date];
sleep(5);

now();

You should see in your console the time logging every 5 seconds.

GCD is very helpful for sending off queues that take a long time (like web fetches – images or db queries – image processing etc).  Your app is still usable while the heavy work is done on another thread that doesn’t obstruct your main thread which is where UIKit stuff used by the user, is handled.

One Comment

Leave a Reply