请稍侯

NSURLConnection 与 NSURLSession 区别

20 June 2016

NSURLConnection 与 NSURLSession 区别

NSURLSession 官方说法

  1. NSURLSession 是iOS7后出来的替代 NSURLConnection 的API;
  2. NSURLSession 通过绑定一个 delegate 在一个网络会话的生命周期里调用某些事件;
  3. NSURLSession 对象是线程安全的;
  4. NSURLSession 默认使用系统提供的delegate,并适当的使用现有的代码使用;
  5. NSURLSession 通过创建 NSURLSessionTask 代表资源被加载的任务,类似 NSURLConnection对象,但相比有更多可控制和定制的 delegate 模型;
  6. NSURLSessionTask 对象创建后是处于挂起状态,只有发-resume消息才会执行;
  7. NSURLSessionTask 的子类 在加载 Data 和 文件下载的使用上有所不同;
  8. NSURLSessionDataTask 接收到资源时会回调 RLSession:dataTask:didReceiveData: 代理method;
  9. NSURLSessionUploadTaskNSURLSessionDataTask 的构造方法不同,他需求显示的引用file或data object;
  10. NSURLSessionDownloadTask 会直接把response data写入到临时文件,网络会话结束后,delegate 会发送一个 URLSession:downloadTask:didFinishDownloadingToURL: 消息来处理下载文件,如果中途取消则会生成一个Blob Data以便下次恢复下载;
  11. 从iOS9开始,使用NSURLSessionStream可以通过一个给定的主机和端口直接建立TCP/IP连接;

NSURLSession的优点(参考:为什么要使用NSURLSession)

  1. 后台上传和下载:只需在创建NSURLSession的时候配置一个选项,就能得到后台网络的所有好处;
  2. 能够暂停和恢复网络操作:使用NSURLSession API能够暂停,停止,恢复所有的网络任务,再也完全不需要子类化NSOperation;
  3. 可配置的容器:对于NSURLSession里面的requests来说,每个NSURLSession都是可配置的容器。举个例来说,假如你需要设置HTTP header选项,你只用做一次,session里面的每个request就会有同样的配置。
  4. 提高认证处理:认证是在一个指定的连接基础上完成的。在使用NSURLConnection时,如果发出一个访问,会返回一个任意的request。此时,你就不能确切的知道哪个request收到了访问。而在NSURLSession中,就能用代理处理认证。
  5. 丰富的代理模式:在处理认证的时候,NSURLConnection有一些基于异步的block方法,但是它的代理方法就不能处理认证,不管请求是成功或是失败。在NSURLSession中,可以混合使用代理和block方法处理认证。

NSURLSession 简单使用

NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:londonWeatherUrl]
      completionHandler:^(NSData *data,
                          NSURLResponse *response,
                          NSError *error) {
        // handle response
}] resume];

NSURLSession 相关的类体系

NSURLSession 类套

NSURLSessionTask

参考: NSURLSession的基本使用 使用NSURLSession

NSURLConnection 官方说法

  1. NSURLConnection本身对网络会话可用操作很少,仅提供了对异步加载 URL request 启动和取消操作;
  2. 利用NSURLConnectionDataDelegate协议,NSURLConnection可以把资源数据直接加载到内存;使用NSURLConnectionDownloadDelegate协议,NSURLConnection可以把资源数据加载到文件;这两个协议都是NSURLConnectionDelegate子协议;
  3. 网络请求结束后,若失败会向delegate发送connection:didFailWithError:消息,若成功或下载成功则会发送connectiondidFinishLoading:connectionDidFinishDownloading消息;
  4. 发送一个-cancel消息会取消当前的网络加载器,但是不能保证其delegate的消息不被继续传递,所以这里要注意当取消了网络加载后其delegate释放后的问题;
  5. 当Connection被建立后,NSURLConnection 会执行一个对NSURLRequest的深拷贝,这个request有可能因对NSURLProtocol 的 canonicalization 或 redirects 而发生改变;
  6. NSURLConnection通过+connectionWithRequest:delegate:a或-initWithRequest:delegate:创建后会在当前的runloop立即执行,没必要发送-start消息;
  7. NSURLConnection通过-initWithRequest:delegate:startImmediately:创建不会立马执,调用-scheduleWithRunLoop:forMode:或-setDelegateQueue:可指定delegate回调的执行上下文,然后调用-start启动加载. 在 -start之前如果没有显式的指runloop,就在当前的runloop模式下默认执行;
  8. NSURLConnectionSynchronousLoading 分类的同步方法+sendSynchronousRequest:returningResponse:error会阻塞当前主线程run loop;NSURLConnectionQueuedLoading 分类的异步方法 +sendAsynchronousRequest:queue:completionHandler提供了异步机制,不会阻塞当前主线程的run loop。同时苹果不建意在加载自定资源时使用这两方法。

使用案例参考:iOS网络篇-NSURLConnection

  • 同步请求:
    //发送同步请求(sendSynchronousRequest)
    NSData *data = [NSURLConnection sendSynchronousRequest:requst returningResponse:&response error:&error];
    
  • 异步请求:
    //发送异步请求(sendAsynchronousRequest)
    [NSURLConnection sendAsynchronousRequest:requst queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
      NSLog(@"----%@",[NSThread currentThread]);
      //解析数据
      NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    
  • 代理请求:
@interface ViewController ()<NSURLConnectionDataDelegate>
    ...
@end

@implementation

    //实现代理中的四个方法
    //1.当接受到服务器响应的时候会调用:response(响应头)
    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {...}
    //2.当接受到服务器返回数据的时候调用(会调用多次)
    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {...}
    //3.当请求失败的时候调用
    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{...}
    //4.当请求结束(成功|失败)的时候调用
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection {...}

    //最后编写点击时调用的方法
    -(void)sendRequestWithDelegate{
        ...
        NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
        //[connect cancel]; 取消
        [connect start];
    }

@end