一、NSURLConnection
我们在前面几节介绍过NSURLConnection发送请求的几种方法,除了同步请求直接获取data,异步请求的以block回调的形式来获取data,NSURLConnection还可以采用代理方法来获取data,方法有点类似XML的sax解析。请求的创建和以前一样,这一节我采用的是Post请求。
- // 1.获取请求网址
- NSURL *url = [NSURL URLWithString:@"http://ipad-bjwb.bjd.com.cn/DigitalPublication/publish/Handler/APINewsList.ashx?"];
-
- // 2.封装请求
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; // post
-
- // 设置请求方式
- [request setHTTPMethod:@"POST"];
-
- // 设置请求体(会把请求的数据转成data,达到用户信息保密的目的)
- NSData *data = [@"date=20131129&startRecord=1&len=5&udid=1234567890&terminalType=Iphone&cid=213" dataUsingEncoding:NSUTF8StringEncoding];
-
- [request setHTTPBody:data];
-
- [NSURLConnection connectionWithRequest:request delegate:self];
既然设置了代理,就要遵守对应的协议。
- <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
NSURLConnectionDelegate的代理方法,主要是用来判断连接状态,处理各类连接情况,常用的就是连接失败。
- - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- {
- // 获取到对应错误信息。
- if(error)
- {
- NSLog(@"%@", [error localizedDescription]);
- }
- }
NSURLConnectionDataDelegate则主要是获取服务器响应,接收数据。
- // 收到服务器响应
- - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- {
- NSLog(@"收到服务器响应");
- }
-
- // 可能多次调用,可以多次拼接获取的数据
- - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- {
- [self.myData appendData:data];
- NSLog(@"收到数据");
- }
-
- // 完成数据接收
- - (void)connectionDidFinishLoading:(NSURLConnection *)connection
- {
- NSError *error = nil;
- NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:self.myData options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error];
-
- if(error)
- {
- NSLog(@"%@", [error localizedDescription]);
- }
-
- NSLog(@"%@", dic);
- }
由于这里面需要拼接数据,所以需要一个容器来保存多次接收的数据,在前面申明一个NSMutableData类型的属性。
- @property (nonatomic, strong) NSMutableData *myData;
- // 懒加载
- - (NSMutableData *)myData
- {
- if(_myData == nil)
- {
- self.myData = [NSMutableData data];
- }
- return _myData;
- }
到这里,一套流程基本完成了。发送请求时候,如果发送出错,调用didFailWithError:方法来输出错误信息。如果没有错误,收到服务器响应,会调用didReceiveResponse:方法。然后从服务器返回数据,通过didReceiveData:方法。如果数据量比较大,这个方法会多次调用,所以需要拼接获取到得数据。最后数据接收完成,会调用connectionDidFinishLoading:方法,这里面可以做数据解析。
二、NSURLSession
在WWDC 2013中,Apple的团队对NSURLConnection进行了重构,并推出了NSURLSession作为替代。
NSURLSession也是一组相互依赖的类,它的大部分组件和NSURLConnection中的组件相同如NSURLRequest,NSURLCache等。而NSURLSession的不同之处在于,它将NSURLConnection替换为NSURLSession和NSURLSessionConfiguration,以及3个NSURLSessionTask的子类:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask。
下面咱们来简单看一下NSURLSession请求数据的流程。前面创建Request的方式不变。
- // 1.获取请求网址
- NSURL *url = [NSURL URLWithString:@"http://ipad-bjwb.bjd.com.cn/DigitalPublication/publish/Handler/APINewsList.ashx?"];
-
- // 2.封装请求
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; // post
-
- // 设置请求方式
- [request setHTTPMethod:@"POST"];
-
- // 设置请求体(会把请求的数据转成data,达到用户信息保密的目的)
- NSData *data = [@"date=20131129&startRecord=1&len=5&udid=1234567890&terminalType=Iphone&cid=213" dataUsingEncoding:NSUTF8StringEncoding];
-
- [request setHTTPBody:data];
-
- // 创建NSURLSession,设置代理,就要遵守协议,配置为默认配置,代理方法执行在主线程。
- NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler:
- ^(NSData *data, NSURLResponse *response, NSError *error) {
- // 获取数据
- NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
-
- NSLog(@"%@", dic);
- }];
-
- [task resume];
代理方法:
- // 在协议的方法中可以完成各种各样的回调动作,如身份验证、完成任务后的动作、错误处理和后台任务完成的动作等。委托方法指定在NSURLSession中一定数量的字节传输使用int64_t类型的参数。
- - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;
-
- - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
- completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler;
-
- - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session NS_AVAILABLE_IOS(7_0);
还有2种创建NSURLSession的方法:
- // NSURLSession *session = [NSURLSession sharedSession];
- // NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
三、总结
其实这两个类的使用流程大差不差,那么苹果为什么要重构一个NSURLSession来替换NSURLConnection呢?
与NSURLConnection相比,NSURLSession最直接的改善就是提供了配置每个会话的缓存,协议,cookie和证书政策(credential policies),甚至跨应用程序共享它们的能力。这使得框架的网络基础架构和部分应用程序独立工作,而不会互相干扰。每一个NSURLSession对象都是根据一个NSURLSessionConfiguration初始化的,该NSURLSessionConfiguration指定了上面提到的政策,以及一系列为了提高移动设备性能而专门添加的新选项。
NSURLSession的另一重要组成部分是会话任务,它负责处理数据的加载,以及客户端与服务器之间的文件和数据的上传下载服务。NSURLSessionTask与NSURLConnection是及其相似的,因为它负责加载数据,而主要的区别在于,任务共享它们父类NSURLSession的共同委托(common delegate)。
简而言之,就是在处理多任务上传下载,频繁切换前台后台的时候,NSURLSession明显是有很大的优势。如果只是像咱们上面这样简单的获取一个JSon数据,其实是看不出来什么差别的,反而还会觉得NSURLSession比较麻烦,毕竟先入为主。咱们教程也是立志于简单使用,如果大家对这些有深入了解的兴趣,不妨可以按照网上一些思路,去自己探索一下。