Today I showed a couple of people at work a technique I use to do asynchronous URL loading in iOS, and the response on Twitter was great, so I’ve written it up for everybody. If you’re used to using ASIHTTPRequest or rolling your own NSURLConnection delegates, hopefully this method will be a breath of fresh air.

The Problem: When you want to load something from the Internet, you don’t want to block your UI—especially when iOS might just kill your app for doing so—but writing delegate code is a pain. You have to remember which delegate methods get called in what order, to set yourself as the delegate (can’t tell you how many times that’s tripped me up), and handling multiple simultaneous connections with one delegate is… tricky, at best.

The Solution: Use Grand Central Dispatch. Maybe I just love GCD too much and this is me seeing everything as a nail, but let’s look at the following code for loading a URL:

[sourcecode language=”objc”]- (void)loadAwesomeURL

{

NSString *awesomeURI = @"http://www.awesomeexample.com/?output=JSON";

NSURL *awesomeURL = [NSURL URLWithString:awesomeURI];

NSURLRequest *awesomeRequest = [NSURLRequest requestWithURL:awesomeURL];

NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:awesomeRequest

delegate:self];

[theConnection start];

}

– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

[myMutableData appendData:data];

}

– (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

[self processTheAwesomeness];

}[/sourcecode]

That sucks. Three methods, and I didn’t even do any error handling! There has to be a better way. NSURLConnection offers a synchronous method, but everybody knows you don’t use it… so let’s do exactly that. But since we want to make this asynchronous, we’ll use Grand Central Dispatch to wrap it in a dispatch_async() call:

[sourcecode language=”objc”]- (void)loadAwesomeURL

{

NSString *awesomeURI = @"http://www.awesomeexample.com/?output=JSON";

NSURL *awesomeURL = [NSURL URLWithString:awesomeURI];

NSURLRequest *awesomeRequest = [NSURLRequest requestWithURL:awesomeURL];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);

dispatch_async(queue, ^{

NSURLResponse *response = nil;

NSError *error = nil;

NSData *receivedData = [NSURLConnection sendSynchronousRequest:awesomeRequest

returningResponse:&response

error:&error];

[self processTheAwesomeness];

});

}[/sourcecode]

We can easily do error checking after the NSURLConnection call; simply check to see if receivedData is nil , cast response to an NSHTTPURLRequest and check its statusCode property, and if all else fails, check out error .

Note: I’ve received a fair amount of negative feedback on this article on Twitter, Reddit, and in the comments, and I feel like I ought to make a few points clear: