NSURLSession VS NSURLConnection
- 根据每个Session做配置(http header,Cache,Cookie,protocal,Credential),不再在整个App层面共享配置.
- 支持网络操作的取消和断点续传
- 改进了授权机制的处理
- 丰富的Delegate模型
- 分离了真实数据和网络配置数据。
- 后台处理上传和下载,即使你点击了“Home”按钮,后台仍然可以继续下载,并且提供了根据网络状况,电力情况进行处理的配置。
用法
使用NSURLSession的一般套路如下:
1. 定义一个NSURLRequest
2. 定义一个NSURLSessionConfiguration,配置各种网络参数
3. 使用NSURLSession的工厂方法获取一个所需类型的NSURLSession
4. 使用定义好的NSURLRequest和NSURLSession构建一个NSURLSessionTask
5. 使用Delegate或者CompletionHandler处理任务执行过程的所有事件。
实战
这儿我简单的实现了一个下载任务的断点续传功能,具体效果如下:
实现代码:
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDownloadDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imgView;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@property (nonatomic,strong) NSURLSessionDownloadTask *task;
@property (nonatomic,strong) NSData *partialData;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.progressView.progress = 0;
// Do any additional setup after loading the view, typically from a nib.
}
- (NSURLSession *)session {
//创建NSURLSession
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
return session;
}
- (NSURLRequest *)request {
//创建请求
NSURL *url = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
return request;
}
- (IBAction)startAction:(UIButton *)sender {
//创建网络任务
self.task = [[self session] downloadTaskWithRequest:[self request]];
[self.task resume];
}
- (IBAction)pauseAction:(UIButton *)sender {
NSLog(@"Pause download task");
if (self.task) {
//取消下载任务,把已下载数据存起来
[self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.partialData = resumeData;
self.task = nil;
}];
}
}
- (IBAction)resumeAction:(UIButton *)sender {
NSLog(@"resume download task");
if (!self.task) {
if (self.partialData) {
self.task = [[self session] downloadTaskWithResumeData:self.partialData];
}else {
self.task = [[self session] downloadTaskWithRequest:[self request]];
}
}
[self.task resume];
}
//创建文件本地保存目录
- (NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location {
NSFileManager *fireManager = [NSFileManager defaultManager];
NSURL *documentsDirectory = [fireManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
return [documentsDirectory URLByAppendingPathComponent:location.lastPathComponent];
}
//把文件拷贝到指定路径
- (BOOL)copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination {
NSError *error;
NSFileManager *fireManager = [NSFileManager defaultManager];
[fireManager removeItemAtURL:destination error:NULL];
[fireManager copyItemAtURL:location toURL:destination error:&error];
if (nil == error) {
return true;
}else {
NSLog(@"%@",error);
return false;
}
}
#pragma mark NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
//下载成功后,文件是保存在一个临时目录的
NSLog(@"Download success for URL: %@",location.description);
NSURL * destination = [self createDirectoryForDownloadItemFromURL:location];
BOOL success = [self copyTempFileAtURL:location toDestination:destination];
if (success) {
//文件保存成功后,使用GCD调用主线程把图片文件显示在UIImageView中
dispatch_async(dispatch_get_main_queue(), ^{
UIImage * image = [UIImage imageWithContentsOfFile:[destination path]];
self.imgView.image = image;
self.imgView.contentMode = UIViewContentModeScaleAspectFit;
});
}else {
NSLog(@"Meet error when copy file");
}
self.task = nil;
}
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
//刷新进度条的delegate方法
double currentPrograss = totalBytesWritten/(double)totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue(), ^{
self.progressView.progress = currentPrograss;
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end