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處理任務執行過程的所有事件。
實戰
這兒我簡單的實現了一個下載任務的斷點續傳功能,具體實現代碼如下:
-(NSURLSession *)session{
if(_session == nil){
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
}
return _session;
}
-(NSURLRequest *)request{
if(_request == nil){
NSURL *url = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];
_request = [NSURLRequest requestWithURL:url];
}
return _request;
}
-(void)startAction{
if(self.isLoading){
NSLog(@"loading...");
return;
}
NSLog(@"start download task");
self.task = [self.session downloadTaskWithRequest:self.request];
[self.task resume];
}
-(void)pauseAction{
if(_task){
NSLog(@"pause download task");
//取消下載任務,把已下載數據保存起來
[self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.imgData = resumeData;
self.task = nil;
}];
}
}
-(void)resumeAction{
if(!_task){
NSLog(@"resume download task");
//判斷是否有已下載數據,有則直接斷點續傳,沒有則重新下載
if(self.imgData){
self.task = [self.session downloadTaskWithResumeData:self.imgData];
}else{
self.task = [self.session downloadTaskWithRequest:self.request];
}
[self.task resume];
}
}
#pragma mark delegate
-(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;
}
/* 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.infoLabel.text = [NSString stringWithFormat:@"進度: %.2f%%", currentProgress];
});
}
//創建文件本地保存目錄
-(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;
}
}