iOS Development Journal

Tips and Tricks Learned the Hard Way

An Example NSURLConnection Delegate

In the little analytics I’ve had to this point, I’ve discovered that people have come here while searching for an example NSURLConnection delegate. So we’re going to walk through an simple example I’ve coded up.

This delegate will fetch a requested URL and make the data available to the class. We’ll allow for simultaneous connections, and callbacks using blocks.

Here’s the header file

Here’s the implementation file

What’s Going On

Let’s look at the full gist and walk through the code.

The Public Interface

There are only two methods and two properties that are public for our delegate. One method allows for the canceling of all running NSURLConnections. The other

1
- (void)fetchURL:(NSURL *)url withCompletion:(ExampleDelegateSuccess)completion failure:(ExampleDelegateFailure)failure;

is used to start a request.

The properties are simple, and allow a user to tweak NSURLRequest’s two primary settings: timeoutInterval and cachePolicy. We’ll set sane defaults so no one has to worry about them.

The Private Interface

We have two additional properties defined. One is a mutable array where we will store active connections. The other is a NSOperationQueue which is where the delegate callbacks will run.

A Private Class

An NSURLConnection doesn’t have much data with it. If we only allowed one call at a time, we could simply have a single property for the data we receive. But since we’ll have multiple connections running at once, it is impractical to manage them1 in our delegate class. Instead we create a child class of NSURLConnection that will store our two blocks and the received data and response. Once a connection is started, it continues to exist until it is complete, so this is an easy place to store such information.

fetchURL:withCompletion:failure:

This method is simple. We create an NSURLRequest and then create a connection with that. If we can’t create a connection, we call the failure block with a custom error2. Then we assign values to our custom properties and start the connection. Once the connection has started we track it in our array.

The Delegate Callbacks (NSURLConnectionDelegate)

You have to implement two delegate protocols to use NSURLConnection. The first NSURLConnectionDelegate only has one required method as of iOS 5.0.

connection:didFailWithError

This is an easy one to handle. We simply call our failure block with the error and remove the connection from our tracking array.

The Delegate Callbacks (NSURLConnectionDataDelegate)

This delegate has the meat of the callbacks3. They handle the responses we receive from the server.

connection:didReceiveResponse:

Apple’s documentation informs us that every time this method is called we need to zero out the received data. Besides that anything we do is up to us. We store the response for use for later, in case of error.

connection:didReceiveData:

This [method][connection:didReceiveData:] provides us with the data the server has sent. We go ahead and append it our connection’s data.

connectionDidFinishLoading:

When this callback is called, we know the connection is done. We don’t know if it was successful, but no more callbacks will be called after this. So here we investigate the response object to see if the call was a success.

Since an HTTP response might indicate failure we check to see if the response if an NSHTTPURLResponse and see if it has an error status code. If so, we call the failure block with an error holding the status code’s message.

If the response wasn’t an HTTP response, or didn’t have an error, we go ahead and call the completion block so the user has the received data.


  1. You might consider managing connections an their associated data with an NSDictionary using the connection as a key. This doesn’t work since NSURLConnection’s don’t implement NSCopying and can’t be used as keys in NSDictionary’s. A CFDictionary works, but is more work with memory management. And don’t even consider using similarly ordered arrays, because then you can’t delete items without weird issues.

  2. This NSError code is ugly and bad. So bad. You shouldn’t use it.

  3. So in pre-iOS 5 these were part of NSURLConnectionDelegate protocol but have since moved into their own. Why two protocols? I don’t know, but that’s how it is.