- NSURLConnection在 iOS9 被宣布弃用,逐渐被 NSURLSession 替代;
- NSURLSession 、 NSURLSessionConfiguration 、NSURLSessionTask 常用三个类;
- AFNetWorking 从2.0版本开始,就是在 NSURLSession 的基础上封装的;
NSURLSession
使用:
1 - 通过NSURLSession的实例创建 task 任务;
2 - resume 执行 task 任务
NSURLSessionTask
可以理解为任务: 数据请求任务,下载任务,上传任务等;
- NSURLSessionTask 的子类
NSURLSessionDataTask 数据请求
NSURLSessionUploadTask 上传
NSURLSessionDownloadTask 下载
NSURLSessionDataTask 数据请求任务
dataTask 是执行数据请求相关的任务,但也可以用来执行上传和下载相关的任务,是我们使用最多的task;
- block 形式
简单的get请求:
如果返回值比较简单,则用这种简单的block方式。
NSURLSession *session = [NSURLSession sharedSession]; //单例创建session对象
NSURL *url = [NSURL URLWithString: "http://www.baidu.com/signin?username=13800138008&password=123456"];
// 初始化task
NSURLSessionTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError error) {
//数据处理
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
[task resume]; // 启动任务 :所有类型的task都要调用resume方法才会开始进行请求
简单的post请求:
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString: @"http://www.baidu.com/signin"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; //post请求
request.HTTPBody = [@"username=13800138008&password=123456" dataUsingEncoding:
NSUTF8StringEncoding];
// 通过request初始化task
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
[task resume];
get 和 post 的区别:
请求方式 | 初始化task | 参数方式 |
---|---|---|
get | url | 参数拼接在 urlString 后面 |
post | request | 将参数通过 utf8 编码,然后放在request 的body中 |
- NSURLSessionDataDelegate 代理形式
简单的数据可以用 block 的方式进行处理,如果返回的数据比较复杂,或者相对数据进一步处理,则使用 NSURLSession 的 delegate。
delegate 分几个阶段 : 响应,接收数据,请求完成;
以get为例:
//创建session: session的delegate属性是只读的;delegateQueue 表示代理方法在哪个队列中执行;
[NSURLSessionConfiguration defaultSessionConfiguration] 表示默认配置
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
// 创建任务
NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com/login?userName=13800138008&password=123456"]]];
[task resume]; // 启动任务
delegate方法:
// 接收到服务器的响应
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
completionHandler(NSURLSessionResponseAllow); // 允许处理服务器的响应,才会继续接收服务器返回的数据
}
// 接收服务器的数据(会调用多次)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
// 处理接收到的数据
}
// 请求完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
// 请求完成,处理成功的数据或者拿到错误的error值
}
NSURLSessionDownloadTask 下载任务
和 一样,有通过 url 和 request 两种方式来初始化 session;
- 通过 url 来初始化,bloc形式:
SURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/source/icon/my.png"] ;
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// 返回的 location 是沙盒中tmp文件夹下的一个临时url,文件下载后会存到这个位置,由于tmp中的文件随时可能被删除,所以我们需要自己需要把下载的文件挪到需要的地方
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent: response.suggestedFilename];
// 移动文件; response.suggestedFilename 是 url 中的最后一部分,如:my.png
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path]
error:nil];
}];
[task resume]; // 启动任务
- NSURLSessionDownloadDelegate 代理的形式:
// 每次写入调用(会调用多次)
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
// 可在这里通过已写入的长度和总长度算出下载进度
CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f",progress);
}
// 下载完成调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
// location 还是一个临时路径,需要自己挪到需要的路径(caches下面)
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
//移动文件
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
}
// 任务完成调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
}
- 断点下载
这种断点下载只支持应用内断点,如果程序在下载过程中途关闭,则不能恢复下载。
// 取消下载 :用这种方式取消下载,可以得到将来用来恢复的数据,保存起来
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData; //保存数据
}];
// 下载失败导致的下载中断会进入此协议方法,也可以得到用来恢复的数据
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// 保存恢复数据
self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
}
// 恢复下载时接过保存的恢复数据
self.task = [self.session downloadTaskWithResumeData:self.resumeData];
[self.task resume]; // 启动任务
NSURLSessionUploadTask 上传任务
上传方式有两种:
1 -
NSURLSessionUploadTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromFile:fileName completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
2 - post 方法: body 参数需要填写request的请求体(http协议规定格式的大长串)
出于安全考虑,用这种方法比较多;
[self.session uploadTaskWithRequest:request fromData: body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
每个task 自身有都拥有下面几个方法
- (void)suspend; 暂停当前任务
- (void)resume; 启动任务,也可以唤醒suspend状态的任务
- (void)cancel; 取消当前的任务,也可以向处于suspend状态的任务发送cancel消息,任务如果被取消便不能再恢复到之前的状态。
NSURLSessionConfiguration 配置
- 默认配置
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 10; // 超时时间
config.allowsCellularAccess = YES; // 是否允许使用蜂窝网络(后台传输不适用)
- task有三种配置
+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 默认模式,会将缓存存储在磁盘上
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 瞬时会话模式,不会创建持久性存储的缓存
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;后台会话模式,允许程序在后台进行上传下载工作