很多iOS开发者使用AFNetWorking完成全部的网络请求,对其中封装的NSURLSession了解很少。这里对NSURLSession做一个介绍。
NSURLSession结构
NSURLSession简单使用
- 创建NSURLSession
- 通过NSURLSession的实例创建task
- 执行task
上面默认自动用Url给你创建了一个get请求的request,如果要换成post请求就需要对request进行处理。//1.url NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/videos.json"]; //2.NSURLSession -> 苹果提供了一个全局的单例,简化我们的开发 NSURLSession * session = [NSURLSession sharedSession]; //3.NSURLSessionDataTask -> 在NSURLSession 开发中,所有的任务都是由Session发起的!! NSURLSessionDataTask * task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //反序列化 id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSLog(@"%@",result); }]; //4.启动任务 [task resume];
上面方法都是使用Block 回调,默认异步的,所以如果要更新UI,需要"线程间通讯"。NSURL *url = [NSURL URLWithString:@"http://www.daka.com/login"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; request.HTTPBody = [@"username=daka&pwd=123" dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession]; // 由于要先对request先行处理,我们通过request初始化task NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); }]; [task resume];
NSURLSession下载
NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/sszip.zip"];
[[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error)
NSLog(@"%@",location);
//这里面放的是下载的目录
}] resume];
这里有个知识点:如果在回调方法中,不做任何处理,下载的文件会被删除,下载文件放在temp里面的,系统会自动回收这块区域。
苹果这样设计的目的是:
- 通常从网络上下载文件,什么格式文件最多 -> zip 文件最多!可以替用户节约流量!
- 如果是 zip 包,下载之后,需要解压。
- 解压缩之后,原始的 zip 文件就不在需要了,系统会自动帮我们删除!
NSURLSession代理
当下载网络数据是需要显示网络下载进度,就需要使用代理了。
- 我们需要一个全局的session来控制下载的暂停或继续。
@property(nonatomic,strong)NSURLSession * session; //这里用懒加载创建session -(NSURLSession *)session { if (_session == nil) { //config 提供了一个全局的网络环境配置,包括:身份验证,浏览器类型,cookie,缓存,超时... //使用Configuration来创建Session,并设置代理 //这里delegateQueue:可以设置代理执行的队列,如果为nil就是子队列。 NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration]; //是否允许后台下载 configuration.discretionary = YES; //请求的最长时限 configuration.timeoutIntervalForRequest = 5; //设置请求头 [configuration setHTTPAdditionalHeaders:@{}]; _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; } return _session; }
- 开始下载任务
NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/abc.wmv"]; //NSURLSession的单例它是全局的,是整个系统的!!!那么我们设置代理不能用全局的设置!! //如果要跟进下载进度,不能使用Block回调的方式! [[self.session downloadTaskWithURL:url] resume];
- 代理
//1. 下载完成方法 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ NSLog(@"完成 %@",location); } //2.下载进度 //1.session //2.downloadTask 调用代理方式的的下载任务! //3.bytesWritten 本次下载的字节数! //4,totalBytesWritten 已经下载的字节数! //5,totalBytesExpectedToWrite 期望下载的字节数-->文件总大小! -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { float progress = (float) totalBytesWritten / totalBytesExpectedToWrite; NSLog(@"%f %@",progress,[NSThread currentThread]); } //3.下载续传数据 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { }
- 取消下载任务
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) { //resumeData : 续传的数据(下载了多少) NSLog(@"数据的长度是: %tu",resumeData.length); self.resumeData = resumeData; //释放下载任务 // - 因为任务都是由Session发起的!!而Session对发起的任务都会持有一个强引用! self.downloadTask = nil; }];
- 继续下载任务
if (self.resumeData == nil) { NSLog(@"哥么没有暂停的任务"); return; } //所有任务都是由session发起的! //使用续传数据启动下载任务 self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData]; //清空续传数据 self.resumeData = nil; //所有的任务都是默认挂起的!! [self.downloadTask resume];
NSURLSession注意点
Session 会对代理进行强引用,当使用了代理,如果任务执行结束后,不取消Session,会出现内存泄露!
//1. 下载完成方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSLog(@"完成 %@",location);
//完成任务,
[self.session finishTasksAndInvalidate];
//清空Session
self.session = nil;
}