iOS—NSURLSession简单使用

NSURLSession,苹果对它的定位是作为NSURLConnection的替代者
NSURLSession的使用相对于之前的NSURLConnection更简单,而且不用处理Runloop相关的东西。

NSURLSession只提供了异步请求方式而没有提供同步请求方式

NSURLSession使用

  • 创建一个USNSURLSession会话对象
  • 根据会话创建task
  • 执行task

NSURLSession的获取

  • 获取共享的session
    可以应对基本的网络请求,这样的session的可定制型很差但是可以满足基本的需求。
    NSURLSession *session = [NSURLSession sharedSession];
  • 获取自定义的session
    在创建一个NSURLSession对象时需要传入一个NSURLConfiguration对象,这个NSURLConfiguration对象管理着网络连接的一些属性,比如是否允许网络使用蜂窝网络等,由同一个session创建的task共享一个NSURLConfiguration对象。传入的NSURLConfiguration对象的类型也决定了创建的NSURLSession的类型。
    这里对于自定义的session的类型、NSURLConfiguration类型、以及几种初始化方式先不过多介绍
    在这里插入图片描述

NSURLSessionTask

通过NSURLSession发起的每个请求,都会被封装为一个NSURLSessionTask任务,但一般不会直接是NSURLSessionTask类,而是基于不同任务类型,被封装为其对应的子类。
在这里插入图片描述

  • NSURLSessionDataTask:处理普通的Get、Post请求。
  • NSURLSessionUploadTask:处理上传请求,可以传入对应的上传文件或路径。
  • NSURLSessionDownloadTask:处理下载地址,提供断点续传功能的cancel方法。

父类NSURLSessionTask中,部分常用方法

  • resume
    开始或继续请求,创建后的task默认是挂起的,需要手动调用resume才可以开始请求。
  • suspend
    挂起当前请求。主要是下载请求用的多一些,普通请求挂起后都会重新开始请求。下载请求挂起后,只要不超过NSURLRequest设置的timeout时间,调用resume就是继续请求。
  • cancel
    取消当前请求。任务会被标记为取消,并在未来某个时间调用URLSession:task:didCompleteWithError:方法。

创建Task

  • NSURLSession提供有普通创建task的方式,创建后可以通过重写代理方法,获取对应的回调和参数。这种方式对于请求过程比较好控制。
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
  • NSURLSession也提供了block的方式创建task,创建方式简单如AFN,直接传入URL或NSURLRequest,即可直接在block中接收返回数据。和普通创建方式一样,block的创建方式创建后默认也是suspend的状态,需要调用resume开始任务。
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;

- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;

completionHandler和delegate是互斥的,completionHandler的优先级大于delegate。相对于普通创建方法,block方式更偏向于面向结果的创建,可以直接在completionHandler中获取返回结果,但不能控制请求过程。

使用NSURLSession发送GET请求

这里仅举例NSURLSessionDataTask

  • Error Domain=kCFErrorDomainCFNetwork Code=-1022 问题
    解决:
    info.plist文件配置
    在这里插入图片描述

block方式创建task

- (void)test {
    //1. 请求路径
    NSURL *url = [NSURL URLWithString:@"http://news-at.zhihu.com/api/4/news/latest"];
   
    //2. 获取会话
    NSURLSession *session = [NSURLSession sharedSession];
    
    
    //3. 创建请求对象
    //请求对象内部默认已经包含了请求头和请求方法(GET)
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //4. 根据会话创建task
//   第一个参数:请求对象
//   第二个参数:completionHandler回调(请求完成【成功|失败】的回调)
//              data:响应体信息(期望的数据)
//              response:响应头信息,主要是对服务器端的描述
//              error:错误信息,如果请求失败,则error有值
    NSURLSessionDataTask *task2 = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            //解析服务器返回的数据
            //此处返回的数据是JSON格式的,因此使用NSJSONSerialization进行反序列化处理
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
            NSLog(@"%@", dic);
        }
    }];
    
    // 发送get请求时,以上3、4步可换成下面注释掉的写法
    //根据会话创建task
//   第一个参数:请求路径
//   第二个参数:completionHandler回调(请求完成【成功|失败】的回调)
//       data:响应体信息(期望的数据)
//       response:响应头信息,主要是对服务器端的描述
//       error:错误信息,如果请求失败,则error有值
    
//  注意:
//   1)该方法内部会自动将请求路径包装成一个请求对象
//      该请求对象默认包含了请求头信息和请求方法(GET)
//   2)如果要发送的是POST请求,则不能使用该方法
//    NSURLSessionDataTask *task1 = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//        if (error == nil) {
//            //解析服务器返回的数据
//            //此处返回的数据是JSON格式的,因此使用NSJSONSerialization进行反序列化处理
//            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
//            NSLog(@"%@", dic);
//        }
//    }];
    
    
    //5. 启动任务
    [task2 resume];
    
}

代理方法

//.m文件
#import "ViewController.h"
@interface ViewController () <NSURLSessionDataDelegate>

@property(nonatomic, strong) NSMutableData *data;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    _data = [[NSMutableData alloc] init];

    [self test3];
}


- (void)test3 {
    //请求路径
    NSURL *url = [NSURL URLWithString:@"http://news-at.zhihu.com/api/4/news/latest"];
    
    //创建请求对象
    //请求对象内部默认已经包含了请求头和请求方法(GET)
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //获得会话对象,并设置代理
//    第一个参数:会话对象的配置信息defaultSessionConfiguration  表示默认配置
//   第二个参数:谁成为代理,此处为控制器本身即self
//   第三个参数:队列,该队列决定代理方法在哪个线程中调用
//   可以传主队列、非主队列
    //NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    
    //创建task
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
    [task resume];
}


//接收到服务器响应的时候调用该方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
        
    NSLog(@"didReceiveResponse");
    
    //注意:
    //和NSURLConnection不同点在于接收到响应信息之后,
    //需要使用completionHandler回调告诉系统应该如何处理服务器返回的数据
    //默认是取消的(NSURLSessionResponseCancel),继续传递数据(NSURLSessionResponseAllow)
    completionHandler(NSURLSessionResponseAllow);
}


//接收到服务器返回数据的时候会调用该方法,如果数据较大那么该方法可能会调用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {

    //拼接服务器返回的数据数据
    [_data appendData:data];
}


//当请求完成(成功\失败)的时候会调用该方法,如果请求失败,则error有值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    NSLog(@"didComplete");

    if (!error) {
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:_data options:NSJSONReadingMutableContainers error:&error];
        NSLog(@"%@", dic);
    }
}

发送POST请求

- (void)test2 {
    NSURL *url = [NSURL URLWithString:@"http://news-at.zhihu.com/api/4/news/latest"];
    
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    //修改请求方式为POST
    request.HTTPMethod = @"POST";
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (!error) {
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
            NSLog(@"%@", dic);
            
        }
    }];
    
    [task resume];
    
     
}

  • NSURLSession的delegate为什么是强引用?

在初始化NSURLSession对象并设置代理后,代理对象将会被强引用。根据苹果官方的注释来看,这个强持有并不会一直存在,而是在调用URLSession:didBecomeInvalidWithError:方法后,会将delegate释放。

通过调用NSURLSession的invalidateAndCancel或finishTasksAndInvalidate方法,即可将强引用断开并执行didBecomeInvalidWithError:代理方法,执行完成后session就会无效不可以使用。也就是只有在session无效时,才可以解除强引用的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值