iOS-NSURLSession与NSURLConnection
一 使用现状
NSURLSession是NSURLConnection 的替代者,在2013年苹果全球开发者大会(WWDC2013)随ios7一起发布,是对NSURLConnection进行了重构优化后的新的网络访问接口。从iOS9.0
开始, NSURLConnection中发送请求的两个方法已过期(同步请求,异步请求),初始化网络连接(initWithRequest: delegate:)的方法也被设置为过期,系统不再推荐使用,建议使用NSURLSession发送网络请求。
- 同步发送请求
// macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response
error:(NSError **)error;
- 异步发送请求
// macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse*response, NSData*data, NSError* connectionError));
- 初始化网络连接
// macos(10.5,10.11), ios(2.0,9.0), tvos(9.0,9.0)
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
// macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
- 简单使用
- (void)useConnection {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/gaoshilist"];
// 2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.异步发送请求
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * response, NSData *data, NSError *connectionError) {
NSLog(@"length:%lu",(unsigned long)data.length);
}];
}
二 普通任务和上传
NSURLSession
针对下载/上传等复杂的网络操作提供了专门的解决方案,针对普通
、上传
和下载
分别对应三种不同的网络请求任务:NSURLSessionDataTask
, NSURLSessionUploadTask
和NSURLSessionDownloadTask.
。创建的task都是挂起状态
,需要resume
才能执行。
- 当服务器返回的数据较小时,NSURLSession与NSURLConnection执行普通任务的操作步骤没有区别。
- 执行上传任务时,NSURLSession与NSURLConnection一样同样需要设置POST请求的请求体进行上传。
普通任务NSURLSessionDataTask
实例代码
- (void)sessionDataTask {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/gaoshilist"];
// 2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.创建 session 对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 普通任务
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse * response, NSError *error) {
if (error) {
NSLog(@"NSURLSessionDataTaskerror:%@",error);
return;
}
// 解析数据
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"NSURLSessionDataTaskdic:%@",dic);
//5.解析数据
NSLog(@"NSURLSessionDataTask:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
// 执行 task
[dataTask resume];
}
执行结果
image.png上传任务时,NSURLSession设置 POST 请求的请求体
- (void)sessionDataTaskPost {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/fankui"];
// 2.创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 设置 post 请求方式
request.HTTPMethod = @"POST";
// 设置请求体
request.HTTPBody = [@"" dataUsingEncoding:NSUTF8StringEncoding];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:queue];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"NSURLSessionDataTaskerror:%@",error);
return;
}
//5.解析数据
NSLog(@"NSURLSessionDataTask:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
[dataTask resume];
}
执行结果
image.png
三 下载任务方式
NSURLConnection
下载文件时,先将整个文件下载到内存,然后再写入沙盒,如果文件比较大,就会出现内存暴涨的情况。
而使用NSURLSessionDownloadTask
下载文件,会默认下载到沙盒中的tem文件夹中,不会出现内存暴涨的情况,但在下载完成后会将tem中的临时文件删除,需要在初始化任务方法时,在completionHandler回调中增加保存文件的代码。 以下代码是实例化网络下载任务时将下载的文件保存到沙盒的caches文件夹中:
NSURLConnection下载文件
-
NSURLConnection
实例代码
- (void)downloadFile {
// 1.创建下载路径
NSURL *url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.4.0.dmg"];
// 2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// NSURLConnection发送异步Get请求,并实现相应的代理方法,该方法iOS9.0之后废除了。
[NSURLConnection connectionWithRequest:request delegate:self];
}
#pragma mark - NSURLConnectionDataDelegate
// 接收到响应的时候:创建一个空的沙盒文件
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"totalLength = %lld",response.expectedContentLength);
}
// 接收到具体数据:把数据写入沙盒文件中
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"data length = %lu",(unsigned long)data.length);
}
// 下载完文件之后调用:关闭文件、清空长度
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"下载完成");
}
打印结果
image.png image.pngNSURLSessionDownloadTask下载文件
-
NSURLSessionDownloadTask
实例代码
- (void)sessionDownloadTask {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://www.pptbz.com/pptpic/UploadFiles_6909/201203/2012031220134655.jpg"];
// 2.创建 session 对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 下载 task
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// 获取沙盒的 caches 路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"img.jpg"];
// 生成 url 路径
NSURL *url = [NSURL fileURLWithPath:path];
// 将文件保存到指定文件目录下
[[NSFileManager defaultManager] moveItemAtURL:location toURL:url error:nil];
}];
[task resume];
}
执行结果 - 断点调试
- 未保存图片之前,下载的资源在临时文件路径下
- 将下载资源从临时路径移动到指定路径下
四 请求方法的控制
-
NSURLConnection
实例化对象,实例化开始,默认请求就发送(同步发送
),不需要调用start方法。而cancel 可以停止请求的发送,停止后不能继续访问,需要创建新的请求。 -
NSURLSession
有三个控制方法,取消(cancel),暂停(suspend),继续(resume),暂停后可以通过继续恢复当前的请求任务。默认不发送请求,需要手动调用resume
方法
五 断点续传的方式
-
NSURLConnection
进行断点下载,通过设置访问请求的HTTPHeaderField
的Range
属性,开启运行循环,NSURLConnection的代理方法作为运行循环的事件源,接收到下载数据时代理方法就会持续调用,并使用NSOutputStream管道流
进行数据保存。
本文参考
NSURLSession与NSURLConnection区别
本文持续更新中,敬请期待。