NSURLSession的基本概念:
三种工作方式:
默认会话模式(default):工作模式类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的整数进行认证授权。
瞬时会话模式(ephemeral)该模式不实用磁盘保存任何数据。所有和会话相关的caches,证书,cookies等都被保存在RAM中,因此当程序使会话无效,这些缓存的数据就会被自动清空。
后台会话模式(background):该模式在后台完成上传和下载,在创建Configuration对象的时候需要提供一个NSString类型的ID用于标识完成工作的后台会话。
NSURLSession支持的三种任务
加载数据 NSURLSessionDataTask
下载 NSURLSessionDownloadTask
上传 NSURLSessionUploadTask
NSURLSessionDataTask
使用协议实现
- (void)dataTask{
//配置会话属性
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//创建任务对象(NSURLSession 使用 代理 或 block)
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//通过url 创建dataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/e1fe9925bc315c60d916f9d58ab1cb134954770d.jpg"]];
[dataTask resume];
}
书写代理的三个方法
//在书写方法之前,我们定义两个全局变量,分别用来接收数据和计算当前进度,以便创建进度条
//在UI上创建一个imgView以及progressView
@interface ViewController ()<NSURLSessionDataDelegate>
{
NSMutableData *_mData;
NSUInteger _expectedContenLenght;
}
@property (weak, nonatomic) IBOutlet UIImageView *imgView;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end
任务收到响应
- (void)URLSession:(NSURLSession *)
session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{
NSLog(@"收到响应");
_mData = [NSMutableData data];
//允许处理服务器的响应,才会继续接收服务器返回的数据
completionHandler(NSURLSessionResponseAllow);
_expectedContenLenght = response.expectedContentLength;
}
收到数据时回调的方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data{
NSLog(@"收到数据");
[_mData appendData:data];
//
self.progressView.progress = (CGFloat) _mData.length / _expectedContenLenght;
}
task完成时实现的方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error{
if (!error) {
//回到主线程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = [UIImage imageWithData:_mData];
});
}
}
用一个touchesBegan来调用方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self dataTask2];
}
使用block实现
- (void)dataTask2{
//配置会话属性
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//创建任务对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
//通过url创建DataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/e1fe9925bc315c60d916f9d58ab1cb134954770d.jpg"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
dispatch_async(dispatch_get_main_queue(), ^{
self.imgView.image = [UIImage imageWithData:data];
});
}
}];
[dataTask resume];
}
NSURLSessionUploadTask
以微博发送信息为例
- (void)uploadTask{
//配置会话模式
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//将string编码后转成url
NSString *urlString = @"https://api.weibo.com/2/statuses/update.json";
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:urlString];
//创建任务对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:60];
NSString *bodyString = [NSString stringWithFormat:@"access_token=填入微博的相关API&status=%@",self.textField.text];
NSData *bodyData = [bodyString dataUsingEncoding:4];
[mRequest setHTTPMethod:@"POST"];
[mRequest setHTTPBody:bodyData];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:mRequest fromData:bodyData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dictionary);
}
}];
[uploadTask resume];
}
使用一个按钮来调用方法
- (IBAction)SendAction:(UIButton *)sender {
[self uploadTask];
}
NSURLSessionDownloadTask,一般用于大文件下载
使用block实现,之后再用touchesBegan来调用,此处不演示
- (void)downloadTask1{
//创建任务对象
NSURLSession *session = [NSURLSession sharedSession];
//创建下载任务
//文件默认下载到tmp文件夹下,当下载完成后,如果没有做任何处理,会被删除,所以要在下载完成的时候将文件
NSURLSessionUploadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/pic/item/023b5bb5c9ea15ce9c017233b1003af33a87b219.jpg"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if (!error) {
//location.path
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 1, YES)objectAtIndex:0];
//建议使用的名字和服务器的名字一样
NSString *fileName = response.suggestedFilename;
NSString *filePath = [cachesPath stringByAppendingString:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager moveItemAtPath:location.path toPath:filePath error:nil];
}
}];
[downloadTask resume];
}
使用协议实现下载以及断点下载
//我们声明三个全局变量,用于在不同方法间使用
@property (nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
@property (nonatomic,strong)NSData *resumeData;
@property (nonatomic,strong)NSURLSession *sessionDownload;
- (void)downloadTask2{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
self.sessionDownload = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.downloadTask = [self.sessionDownload downloadTaskWithURL:[NSURL URLWithString:@"http://b.zol-img.com.cn/desk/bizhi/image/7/2560x1600/145135666476.jpg"]];
[self.downloadTask resume];
}
数据下载完成,此方法为必选方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
//数据下载完成后保存到caches文件夹下
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString *filePath = [cachesPath stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager moveItemAtPath:location.path toPath:filePath error:nil];
}
此方法用于显示当前下载进度条,此方法为可选方法
/*
每当下载完一部分数据就会走这个方法
session 任务对象
downloTask 下载任务
bytesWritten 本次写到文件里面的数据
totalBytesWritten 已经写入到文件的数据
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;
}
断点下载实现代码
- (IBAction)btnAction:(UIButton *)sender {
if ([sender.titleLabel.text isEqualToString:@"下载"]) {
[sender setTitle:@"暂停" forState:UIControlStateNormal];
if (self.resumeData == nil) {
[self downloadTask2];
}
else{
self.downloadTask = [self.sessionDownload downloadTaskWithResumeData:self.resumeData];
[self.downloadTask resume];
}
}
else{
[sender setTitle:@"下载" forState:UIControlStateNormal];
[self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData;
}];
self.downloadTask = nil;
}
}