Does NSURLSession for HTTP data task (NSURLSessionDataTask) runs in background thread or we will have to provide the queue?

NSPratik picture NSPratik · Jul 31, 2015 · Viewed 8.9k times · Source

I started to use NSURLSession by avoiding NSURLConnection now a days as it's a new and elegant API provided by Apple. Previously, I used to put call NSURLRequest in GCD block to execute it in background. Here is how I used to do in past:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSURLRequest *request = [NSURLRequest requestWithURL:
                             [NSURL URLWithString:@"www.stackoverflow.com"]];
    NSURLResponse *response;
    NSError *error;
    NSData *data = [NSURLConnection sendSynchronousRequest:request 
                                         returningResponse:&response 
                                                     error:&error];
    if (error) {
        // handle error
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        // do something with the data
    });
});

Now, here is how I use NSURLSession:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    /*-----------------*
        NSURLSession
     *-----------------*/

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:
                                  [NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] 
                                     completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) 
{
    NSDictionary *json = [NSJSONSerialization 
                          JSONObjectWithData:data options:0 error:nil];
    NSLog(@"%@", json);
}];
}

I want to know that, will my request be executed on background thread itself or I will have to provide my own mechanism same way I did in case of NSURLRequest ?

Answer

Rob picture Rob · Jul 31, 2015

No, you don't need to use GCD to dispatch this to background queue. In fact, because the completion block runs on background thread, the exact opposite is true, that if you need anything in that block to run on the main queue (e.g., synchronized updates to model objects, UI updates, etc.), you have to manually dispatch that to the main queue yourself. For example, let's imagine that you were going to retrieve a list of results and update the UI to reflect this, you might see something like:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // this runs on background thread

        NSError *error;
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

        // detect and handle errors here

        // otherwise proceed with updating model and UI

        dispatch_async(dispatch_get_main_queue(), ^{
            self.searchResults = json[@"results"];    // update model objects on main thread
            [self.tableView reloadData];              // also update UI on main thread
        });

        NSLog(@"%@", json);
    }];

    [dataTask resume];
}