URLSession的基本概念
1.三种工作方式:
默认会话模式(default):
工作模式类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的整数进行认证授权。
瞬时会话模式(ephemeral)
该模式不使用磁盘保存任何数据。所有和会话相关的caches,证书,cookies等都被保存在RAM中,因此当程序使会话无效,这些缓存的数据就会被自动清空。
后台会话模式(background):
该模式在后台完成上传和下载,在创建Configuration对象的时候需要提供一个NSString类型的ID用于标识完成工作的后台会话。
2.NSURLSession支持的三种任务
NSURLSession类支持三种类型的任务:加载数据
,下载
,上传
。
NSURLSession的类:NSURLSessionConfiguration类、NSURLSession类、NSURLSessionTask类
NSURLSessionConfiguration
NSURLSessionConfiguration类
其中NSURLSessionConfiguration用于配置会话的属性,可以通过该类配置会话的工作模式
+(NSURLSessionConfiguration*)defaultSessionConfiguration;//一般使用默认的
NSURLSession类
获取NSURLSession类对象有几种方式:
+ (NSURLSession *)sharedSession;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
第一种方式是使用静态`shareSession`方法,该类使用共享的话,该会话使用全局的Cache,Cookie和证书。
第二种方式是通过`sessionWithConfiguration:`方法创建对象,也就是创建对应配置的会话,与NSURLSessionConfiguration合作使用。
第三种方式是通过`sessionWithConfiguration:delegate:delegateQueue:`方法创建对象,二三两种方式可以创建一个新会话并指定其会话类型。该方式中指定了session的委托和委托所处的队列。当不再需要连接时,可以调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate 等待当前Task结束后关闭。这时Delegate会收到 - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error; 这个事件。Delegate收到这个事件之后会被解引用。
NSURLSessionTask
NSURLSessionTask是一个抽象子类,它有三个子类:`NSURLSessionDataTask`,`NSURLSessionUploadTask`和`NSURLSessionDownloadTask`。这三个类封装了现代应用程序的三个基本网络任务:`获取数据`,比如JSON和XML,以及`上传`和`下载`文件。
NSURLSessionDataTask
代码示例如下:
- (void)dataTask{
//1.配置会话属性
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//2.创建任务对象(NSURLSession 代理或者block)
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegate:[NSOperationQueue mainQueue]];
//3.通过url 创建dataTask
NSURLSessionDataTask *dagaTask = [session dataWithURL:[NSURL URLWithString:@"http://b.zol-img.com.cn/desk/bizhi/image/7/2560x1600/145135666476.jpg"]];
//4.开始启动任务
[dataTask resume];
}
NSURLSessionUploadTask
- (void)uploadTask{
//配置会话属性
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//创建session对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
//创建mRequest请求
NSString *urlString = @"https://api.weibo.com/2/statuses/update.json";
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
//参数转换及设置方法体
NSString *bodyString = [NSString stringWithFormat:@"access_token=2.00zMf9ND9ip3KCc14c03c2900L6tAc&status=%@",self.textFieldView.text];
NSData *data = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
[mRequest setHTTPMethod:@"POST"];
[mRequest setHTTPBody:data];
//创建uploadTask
NSURLSessionTask *uploadTask = [session uploadTaskWithRequest:mRequest fromData:data completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"dictionary = %@",dictionary);
}
}];
[uploadTask resume];
}
NSURLSessionDownloadTask
- (void)downloadTask {
//设置会话属性
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//创建session对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
//创建下载任务downloadTask
//文件默认下载到tmp文件夹,当下载完成时没有任何的处理会被删掉,所以在下载完成时把文件转移到另一个文件夹中
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/pic/item/023b5bb5c9ea15ce9c017233b1003af33a87b219.jpg"] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//拿到cashesPath路径(Library/cashes)
NSString *cashesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//建议使用的名字和服务器的一样
NSString *fileName = response.suggestedFilename;
NSString *filePath = [cashesPath stringByAppendingPathComponent:fileName];
//移动文件,需要用到NSFileManager
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager moveItemAtPath:location.path toPath:filePath error:nil];
dispatch_async(dispatch_get_main_queue(), ^{
NSData *data = [NSData dataWithContentsOfFile:filePath];
self.imgView.image = [UIImage imageWithData:data];
});
}];
//启动任务
[downloadTask resume];
NSLog(@"下载");
}
//使用代理实现断点续传
- (void)downloadTask2{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session =[NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//创建下载任务
_downTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://b.zol-img.com.cn/desk/bizhi/image/7/2560x1600/145135666476.jpg"]];
//开启任务
[_downTask resume];
self.sessionDownload = session;
}
#pragma mark --NSURLSessionDownloadDelegate--
//数据下载完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];//objectAtIndex:0
NSString *filePath = [cachePath stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
//location 代表源地址
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager moveItemAtPath:location.path toPath:filePath error:nil];
}
/**
* 每当下载完一部分数据就会走方法(不是必须要实现的方法)
*
* @param session 任务对象
* @param downloadTask 下载任务
* @param bytesWritten 本次写到文件里面的数据
* @param totalBytesWritten 已经写入到文件的数据
* @param totalBytesExpectedToWrite 文件总长度
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
self.progressView.progress = (CGFloat)totalBytesWritten/totalBytesExpectedToWrite;
NSLog(@"%.2f",self.progressView.progress);
}
- (IBAction)buttonAction:(UIButton *)sender {
// [self downloadTask2];
//titleLabel
if ([sender.titleLabel.text isEqualToString:@"下载"]) {
[sender setTitle:@"暂停" forState:UIControlStateNormal];
if (self.resumeData == nil) {
[self downloadTask2];
}
else{
self.downTask = [self.sessionDownload downloadTaskWithResumeData:_resumeData];
[self.downTask resume];
}
}
else{
[sender setTitle:@"下载" forState:UIControlStateNormal];
[self.downTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.resumeData = resumeData;
}];
self.downTask = nil;
}
}