Tuesday, March 24, 2015

Simple NSURLConnection vs NSURLSession example

This is a simple example of how to achieve the same simple GET call with (the "old") NSURLConnection and the new NSURLSession.
This project is in Objective-C.

Update: I just finished the exact same tutorial using swift (link)

The final result
This a simple app with 2 buttons, 1 label and 1 UIImageView.

When you tap the "NSURLConnection" the app downloads a picture of a car using NSURLConnection.
When you tap the "NSURLSession" the app downloads a picture of a car using NSURLSession.
The label also updates to tell you which one you're using.


Here's the code to get this GET call using NSURLConnection:
- (IBAction)button_useNSURLConnection:(id)sender
    label_status.text = @"Selected NSURLConnection";
    NSURL *url = [NSURL URLWithString:URL_CAR_1];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    dispatch_queue_t loadQ = dispatch_queue_create("DownloadQueue", NULL);
                      NSData *data = [NSURLConnection sendSynchronousRequest:request
                                         imageView.image = [UIImage imageWithData:data];

I decided to make the NSURLConnection a Synchronous request so it can return a value (Asynchronous would just give me a value in a easier way, but that's not fun), but this means it runs in the main thread.
  1. We get a URL from a String (a constant I have defined in my class)
  2. We make a MutableURLRequest with the url of step 1
  3. Set the HTTP method of the request to GET
  4. Created a new GCD queue
  5. Used the new GCD queue to make the actual NSURLConnection in a different/background thread
  6. Once the background thread is completed, I'm calling the main GCD queue (main/UI thread) to place the downloaded image into the imageView


NSURLSession is a bit different. An NSURLSession has be created with a NSURLSessionConfiguration first. Because of this I created a helper method that generates a NSURLSession with the configuration needed, and it returns the NSURLSession it creates:
- (NSURLSession *)getURLSession
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
                      NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
                      session = [NSURLSession sessionWithConfiguration:configuration];
    return session;

Since I don't want slow down the main thread for this, I placed this code in a different thread.
Then, here's how to make the NSURLSession call:
- (IBAction)button_useNSURLSession:(id)sender
    label_status.text = @"Selected NSURLSession";
    NSURL *url = [NSURL URLWithString:URL_CAR_2];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    NSURLSessionDataTask *task = [[self getURLSession]
                                  completionHandler:^(NSData *data,
                                                      NSURLResponse *response,
                                                      NSError *error)
                           imageView.image = [UIImage imageWithData:data];
    [task resume];

Very similar to the NSURLConnection, so I'll start at the NSURLSessionDataTask.
Technically, NSURLSession does not replace NSURLConnection, but NSURLSessionDataTask is what replaces NSURLConnection.

  1. NSURLSessionDataTask is an Asynchronous task, so we're kind of forced to get the data from its completion handler
  2. Call the main/UI thread and set the value of the imageView with the data from the completion handler
  3. Set the task to [task resume] so it can start
That's all!

The sample code can be found here.


1 comment: