Search code examples
iosobjective-cdelegatesnsurlconnectionnsurlsession

NSURLSession delegate vs. completionHandler


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?


Solution

  • 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