NSURLSession可以看做是NSURLConnection的进化版,其对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 "UrlSessionDemoViewController.h" @interface UrlSessionDemoViewController () @end @implementation UrlSessionDemoViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; return self; } - (void)viewDidLoad { [super viewDidLoad]; self.progressBar.progress = 0; } - (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)start:(id)sender { //用NSURLSession和NSURLRequest创建网络任务 self.task = [[self session] downloadTaskWithRequest:[self request]]; [self.task resume]; } -(IBAction)pause:(id)sender { NSLog(@"Pause download task"); if (self.task) { //取消下载任务,把已下载数据存起来 [self.task cancelByProducingResumeData:^(NSData *resumeData) { self.partialData = resumeData; self.task = nil; }]; } } -(IBAction)resume:(id)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 *fileManager = [NSFileManager defaultManager]; NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory = urls[0]; return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]]; } //把文件拷贝到指定路径 -(BOOL) copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination { NSError *error; NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager removeItemAtURL:destination error:NULL]; [fileManager copyItemAtURL:location toURL:destination error:&error]; if (error == nil) { 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.imageView.image = image; self.imageView.contentMode = UIViewContentModeScaleAspectFit; self.imageView.hidden = NO; }); }else{ NSLog(@"Meet error when copy file"); } self.task = nil; } /* Sent periodically to notify the delegate of download progress. */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { //刷新进度条的delegate方法,同样的,获取数据,调用主线程刷新UI double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite; dispatch_async(dispatch_get_main_queue(), ^{ self.progressBar.progress = currentProgress; self.progressBar.hidden = NO; }); } - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
所有代码在这儿: https://github.com/xianlinbox/iOS7_New/tree/master/iOS7_New/NSURLSession/ViewController
参考文章: http://www.objc.io/issue-5/from-nsurlconnection-to-nsurlsession.html
http://www.shinobicontrols.com/blog/posts/2013/09/20/ios7-day-by-day-day-1-nsurlsession