NSURLSession delegate vs. completionHandler

AndrewSB picture AndrewSB · Mar 26, 2014 · Viewed 28.1k times · Source

I've always used completion handlers. With NSURLConnection and now with NSURLSession. It's led to my code being really untidy, especially I have request within request within request.

I wanted to try using delegates in NSURLSession to implement something I've done untidily with NSURLConnection.

So I created a NSURLSession, and created a dataTask:

NSURLSessionDataTask *dataTask = [overallSession dataTaskWithURL:url
                                                  completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                      if(error == nil)
                                                      {
                                                          NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
                                                          NSLog(@"Data = %@",text);
                                                      }

                                                  }];

    [dataTask resume];

Right now I have a completionHandler for the response, how would I switch to delegates to manage the response and data? And can I add another dataTask from the delegate of this one? Using the cookies that this dataTask created and placed into the session?

Answer

Vacca picture Vacca · Dec 10, 2014

If you want to add a custom delegate class, you need to implement the NSURLSessionDataDelegate and NSURLSessionTaskDelegate protocols at the minimum.

With the methods:

NSURLSessionDataDelegate - get continuous status of your request

 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {

    receivedData=nil; receivedData=[[NSMutableData alloc] init];
    [receivedData setLength:0];

    completionHandler(NSURLSessionResponseAllow);
}

NSURLSessionDataDelegate

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
   didReceiveData:(NSData *)data {

    [receivedData appendData:data];
}

NSURLSessionTaskDelegate

 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
 if (error) {
  // Handle error
 }
else {
   NSDictionary* response=(NSDictionary*)[NSJSONSerialization JSONObjectWithData:receivedData options:kNilOptions error:&tempError];
    // perform operations for the  NSDictionary response
}

If you want to separate the delegate code (middle layer) from your calling class (generally its good practice to have separate class/layer for network calls), the delegate of NSURLSession has to be :-

NSURLSession *session=[NSURLSession sessionWithConfiguration:sessionConfig delegate:myCustomDelegateClass delegateQueue:nil];

Ref Links:

  1. NSURLSession Class Reference
  2. iOS NSURLSession Example (HTTP GET, POST, Background Downlads )
  3. From NSURLConnection to NSURLSession