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.

NSURLConnection

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);
    dispatch_sync(loadQ,
                  ^{
                      NSData *data = [NSURLConnection sendSynchronousRequest:request
                                                           returningResponse:nil
                                                                       error:nil];
                      dispatch_async(dispatch_get_main_queue(),
                                     ^{
                                         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

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;
    dispatch_once(&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]
                                  dataTaskWithRequest:request
                                  completionHandler:^(NSData *data,
                                                      NSURLResponse *response,
                                                      NSError *error)
    {
        dispatch_async(dispatch_get_main_queue(),
                       ^{
                           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.

Eduardo.

1 comment: