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

1

23

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), ^{

    NSURL *url = [NSURL URLWithString:@"www.stackoverflow.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    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
     *-----------------*/

    NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url
                                            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 ?

Concertmaster answered 31/7, 2015 at 12:28 Comment(3)
sendAsynchronousRequest runs in background despite we don't provide any background queue...Concertmaster
Rob, will I have to put my NSURLSession code block into GCD queue to make it run in background ? Please refer to my code block written in question itself..Concertmaster
@T_77 All of the NSURLSession methods. The geocoder and the location search methods. Many of the Cocoa methods that are doing something asynchronously and have completion blocks/closures do so on background thread.Petrolatum
P
52

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];
}
Petrolatum answered 31/7, 2015 at 13:20 Comment(4)
Thank you for your answer, do you know what's the difference when using URLSessionConfiguration.background ?Encyst
@theReverend - The answer is basically the same, that the session will run asynchronously with respect to the thread from which you started it and you should feel free to start it from the main thread (and make sure to dispatch code in the completion handlers back to the main queue if updating UI or model objects). The “background” in “background session” has nothing to do with the queues/threads issue, but rather is related to the state of the app (i.e. it will continue to run even if the app leaves foreground).Petrolatum
Not sure about that, because in similar method of AFHTTPSessionManager [manager dataTaskWithRequest:...] code in completion could be called in main thread (checked by [NSThread isMainThread])Barfly
Yes, I am sure about that. First, AFNetworking (and Alamofire) dispatch their completion handlers back to the main queue as a matter of convenience. This has no bearing on the OP’s original question. Second, you can even configure NSURLSession to use the main queue, too, if you really wanted. But, again, it does not matter. It does not change the fact that network requests are asynchronous. You never need to dispatch the start of the network request via GCD, as proposed by the OP.Petrolatum

© 2022 - 2024 — McMap. All rights reserved.