iOS - Objective-C - Downloading Data using NSURLConnection

Stephen Zaharuk / Thursday, May 15, 2014

In this always connected cloud based world we live in today, i'm willing to bet that the App you're currently working on, needs to download some sort of data. Whether it be files from some type of cloud storage, or even just requesting tweets from twitter.  Today i'm going to talk about NSURLConnection and how it can be used to download data.

Note:It's not their latest technology by any means, in fact in iOS 7 they introduced NSURLSession which essentially replaces it. However, if you want to provide support for older devices this article should be able to help. 

The first thing you're going to want to do, is make sure you implement the NSURLConnectionDelegate protocol. This requires you to implement the following 3 selectors:

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data


- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error


- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection

Next lets define a couple of fields that we'll use to store data and keep track of our connection.

NSMutableData* _dataResponse;
NSURLConnection* _connection;

Now lets get to the fun part. Once you have a url for downloading a chunk of data, you can create your NSURLConnection object:

_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

The first parameter is your NSURLRequest, followed by the object that implemented the NSURLConnectionDelegate that I mentioned earlier.

In this instance i'm going to tell it not to start immediately. The reason for this is that i don't want other threads to block it from downloading. What i mean by this, is that if you were doing anything else while it was downloading, it could actually stop the connection from downloading until you finished. 

Since we created the connection, but have not told it to start yet, we need to manually tell it to begin downloading. 

[_connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[_connection start];

By scheduling it in the main loop, we make sure that it doesn't get blocked. 

So now that we've begun downloading, lets capture the data that is returned. That will happen in the following protocol method:

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
{
   if (_dataResponse == nil)
      _dataResponse = [[NSMutableData alloc] initWithCapacity:2048];

   [_dataResponse appendData:data];
}

Depending on how large your file is, this method can get called multiple times until your file is fully downloaded. If you know the size of the file you're downloading, this is a good place to insert a progress indicator code that you can show your users. 

If we haven't instantiated our NSMutableData object yet, we'll go ahead and do that here, and then append any data we've downloaded. 

During the download there could be an error thrown, for example if the user lost their internet connection. That should be handled in the following protocol method:

- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error
{
   // Handle any error that occured.
}

Finally, when the download has completed the last method in our protocol will be invoked. At that point we can take our data and process it. For example, if it was JSON data, we could then use the NSJSONSerialization to load it:

- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
{
   NSDictionary *results =[NSJSONSerialization JSONObjectWithData:_dataResponse options:kNilOptions error:nil];

  _dataResponse = nil;

  // Do Something with the json.
}

One last thing. If for some reason something happens in your App and you want to stop downloading a particular connection, you can simply call cancel on your connection object:

[_connection cancel];

And thats how you download data using NSURLConnection. 

Enjoy!

By Stephen Zaharuk (SteveZ)