简介
- NSURLConnection在iOS9被宣布弃用,NSURLSession从13年发展到现在,终于迎来了它独步江湖的时代.NSURLSession是苹果在iOS7后为HTTP数据传输提供的一系列接口,比NSURLConnection强大,坑少,好用
默认是挂起的,执行要resume
NSURLSession 的优势
- NSURLSession 支持 http2.0 协议
- 在处理下载任务的时候可以直接把数据下载到磁盘
- 支持后台下载|上传
- 同一个 session 发送多个请求,只需要建立一次连接(复用了TCP)
- 提供了全局的 session 并且可以统一配置,使用更加方便
- 下载的时候是多线程异步处理,效率更高
- 内存消耗很低
NSURLSessionTask 的子类
- NSURLSessionTask 是一个抽象类,如果要使用那么只能使用它的子类
- NSURLSessionTask 有两个子类
- NSURLSessionDataTask,可以用来处理一般的网络请求,如 GET | POST 请求等
- NSURLSessionDataTask 有一个子类为 NSURLSessionUploadTask,用于处理上传请求的时候有优势
-
NSURLSessionDownloadTask,主要用于处理下载请求,有很大的优势
- NSURLSessionDataTask,可以用来处理一般的网络请求,如 GET | POST 请求等
GET请求
//1.url
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/demo.json"];
//2.NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
//3.获取task
// 根据对象创建 Task 请求
//
// url 方法内部会自动将 URL 包装成一个请求对象(默认是 GET 请求)
// completionHandler 完成之后的回调(成功或失败)
//
// param data 返回的数据(响应体)
// param response 响应头
// param error 错误信息
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];
POST请求
//1.url
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/demo.json"];
//2.创建可变请求对象
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url];
//2.1修改请求方法
requestM.HTTPMethod = @"POST";
//2.2设置请求体
requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//创建会话对象
NSURLSession *session = [NSURLSession sharedSession];// 是全局的单例。整个系统。不建议用这个
//3.创建请求 Task
NSURLSessionTask *task = [session dataTaskWithRequest:requestM completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@",result);
}];
//4.启动任何
[task resume];
NSURLSessionDataTask 设置代理发送请求
- 创建 NSURLSession 对象设置代理
- 使用 NSURLSession 对象创建 Task
- 执行 Task
//确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
//创建可变请求对象
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url];
//设置请求方法
requestM.HTTPMethod = @"POST";
//设置请求体
requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//创建会话对象,设置代理
/**
第一个参数:配置信息
第二个参数:设置代理
第三个参数:队列,如果该参数传递nil 那么默认在子线程中执行
*/
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self delegateQueue:nil];
//创建请求 Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestM];
//发送请求
[dataTask resume];
- 遵守协议,实现代理方法(常用的有三种代理方法)
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask
didReceiveResponse:(nonnull NSURLResponse *)response
completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
//子线程中执行
NSLog(@"接收到服务器响应的时候调用 -- %@", [NSThread currentThread]);
self.dataM = [NSMutableData data];
//默认情况下不接收数据
//必须告诉系统是否接收服务器返回的数据
completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
NSLog(@"接受到服务器返回数据的时候调用,可能被调用多次");
//拼接服务器返回的数据
[self.dataM appendData:data];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
NSLog(@"请求完成或者是失败的时候调用");
//解析服务器返回数据
NSLog(@"%@", [[NSString alloc] initWithData:self.dataM encoding:NSUTF8StringEncoding]);
}
设置代理之后的强引用问题
- NSURLSession 对象在使用的时候,如果设置了代理,那么 session 会对代理对象保持一个强引用,在合适的时候应该主动进行释放
- 可以在控制器调用 viewDidDisappear 方法的时候来进行处理,可以通过调用 invalidateAndCancel 方法或者是
finishTasksAndInvalidate 方法来释放对代理对象的强引用- invalidateAndCancel 方法直接取消请求然后释放代理对象
- finishTasksAndInvalidate 方法等请求完成之后释放代理对象。
[self.session finishTasksAndInvalidate];
文件下载
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/sszip.zip"];
/*
如果在回调方法中,不做任何处理,下载的文件会被删除
下载文化是默认下载到tmp文件夹,系统会自动回收这个区域
设计目的:
1.通常从网络下载文件,什么样的格式文件最多?zip
2.如果是zip包,下载之后要解压
3.解压之后,原始的zip就不需要了。系统会自动帮你删除
*/
[[[NSURLSession sharedSession]downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",location);
//文件解压目标路径,不能指定目标文件。因为我们解压文件会产生多个文件
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
[SSZipArchive unzipFileAtPath:location.path toDestination:cachePath];
//工具类路径http://download.csdn.net/download/liyanjun201/10127149
}]resume];
设置下载进度和断电续传
@interface ViewController ()
//全局的网络会话,管理所有的网络任务
@property(nonatomic,strong)NSURLSession *session;
@property (weak, nonatomic) IBOutlet CCProgressBtn *progressView;
@property(nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
@property(nonatomic,strong)NSData *resumeData;
@end
@implementation ViewController
-(NSURLSession *)session
{
if (_session == nil) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _session;
}
-(void)dealloc
{
NSLog(@"走了!");
}
//静态库:每一个应用程序都会需要一个副本
//动态库,在系统中只有1个副本,只有苹果公司能够建立动态库,开发者建立的动态库是不允许上架
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.session invalidateAndCancel];
self.session = nil;
}
- (IBAction)start:(id)sender {
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/abc.wmv"];
self.downloadTask = [self.session downloadTaskWithURL:url];
[self.downloadTask resume];
}
- (IBAction)pause:(id)sender {
NSLog(@"暂停!");
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
NSLog(@"数据的长度是:%tu",resumeData.length);
self.resumeData = resumeData;
//释放任务
self.downloadTask = nil;
}];
}
- (IBAction)resumeClick:(id)sender {
if (_resumeData == nil) {
return;
}
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
self.resumeData = nil;
[self.downloadTask resume];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/abc.wmv"];
//如果你要监听下载进度,必须使用代理。
//[NSURLSession sharedSession] 是全局的单例。整个系统å
//如果你要更进下载进度,就不能block 。
[[self.session downloadTaskWithURL:url]resume];
}
#pragma mark --NSURLSessionDelegate
//下载完成
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"下载完成!");
[self.session finishTasksAndInvalidate];
self.session = nil;
}
//2下载进度
/*
session :
downloadTask :调用代理方式的下载任何
bytesWritten:本次下载的字节数
totalBytesWritten:已经下载的字节数
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);
NSLog(@"%@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
self.progressView.progress = progress;
});
}
//3.下载续传数据
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
@end