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?
Like most networking APIs, the NSURLSession API is highly asynchronous.
“In iOS7 and later or OS X v10.9 and later, NSURLSession is the preferred API for new code that performs URL requests” — Apple. Usually, when an iOS developers wants to retrieve contents from certain URL, they choose to use NSURLConnection.
NSURLSession introduces a new pattern to Foundation delegate methods with its use of completionHandler: parameters. This allows delegate methods to safely be run on the main thread without blocking; a delegate can simply dispatch_async to the background, and call the completionHandler when finished.
If you want to add a custom delegate class, you need to implement the NSURLSessionDataDelegate
and NSURLSessionTaskDelegate
protocols at the minimum.
With the methods:
- (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); }
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { [receivedData appendData:data]; }
- (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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With