NSURLSession下載與緩存
iOS9要求網(wǎng)絡(luò)請求需要使用NSURLSession,那么本篇文章
就使用NSURLsession來實(shí)現(xiàn)視頻的下載,圖片的下載、取消下載、恢復(fù)下
載和緩存功能,期望與大家一起學(xué)習(xí)。
-
NSURLSessionConfiguration(參數(shù)配置類)NSURLSession狀態(tài)同時對應(yīng)著多個連接,不像之前使用共享的一個全局狀態(tài)。會話是通過工廠方法(類方法)來創(chuàng)建對象
NSURLSessionConfiguration。總共有三種會話:
1.
defaultSessionConfiguration默認(rèn)的,進(jìn)程內(nèi)會話2.
ephemeralSessionConfiguration短暫的(內(nèi)
存),進(jìn)程內(nèi)會話
3.backgroundSessionConfigurationWithIdentifier后臺會話
-
相關(guān)屬性
//后臺任務(wù)的標(biāo)識符 @property (nullable, readonly, copy) NSString *id entifier; //緩存的策略 @property NSURLRequestCachePolicy requestCachePolicy; //請求超時時長 @property NSTimeInterval timeoutIntervalForRequest; //網(wǎng)絡(luò)服務(wù)類型 @property NSURLRequestNetworkServiceType networkServiceType; //是否在非無線的情況下請求網(wǎng)絡(luò) @property BOOL allowsCellularAccess;
手動下載視頻
-
步驟:
在Info.plist中添加NSAppTransportSecurity類型Dictionary。
在NSAppTransportSecurity下添加NSAllowsArbitraryLoads類型Boolean,值設(shè)為YES;在工程內(nèi)引入AVFoundation框架,并在相關(guān)類引入AVKit、AVFoundation頭文件;
遵守NSURLSessionDelegate,NSURLSessionDownloadDelegate協(xié)議;
準(zhǔn)備一個MP4格式的url,進(jìn)行下載;
將下載完成的視頻資源存入本地,并進(jìn)行播放。
聲明相關(guān)屬性
//下載任務(wù)
@property (nonatomic, strong)NSURLSessionDownloadTask *downTask;
//網(wǎng)絡(luò)會話
@property (nonatomic, strong)NSURLSession * downLoadSession;
- 配置相關(guān)參數(shù)并下載
//參數(shù)設(shè)置類 簡單的網(wǎng)絡(luò)下載使用
defaultSessionConfiguration即可
NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration
defaultSessionConfiguration];
//創(chuàng)建網(wǎng)絡(luò)會話
self.downLoadSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue new]];
//數(shù)據(jù)請求
/*
*@param URL 資源url
*@param timeoutInterval 超時時長
*/
NSURLRequest *imgRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:MP3URL] cachePolicy:5 timeoutInterval:60.f];
//創(chuàng)建下載任務(wù)
self.downTask = [self.downLoadSession downloadTaskWithRequest:imgRequest];
//啟動下載任務(wù)
[self.downTask resume];
- 實(shí)現(xiàn)代理方法
#pragma mark 下載過程
-(void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
//獲取下載進(jìn)度
double currentProgress = totalBytesWritten / (double)totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue(), ^{
//進(jìn)行UI操作 設(shè)置進(jìn)度條
self.downLoadProgress.progress = currentProgress;
});
#pragma mark 下載完成 無論成功失敗
-(void)URLSession:(NSURLSession *)session task: (NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@" function == %s, line == %d, error == %@",__FUNCTION__,__LINE__,error);
}
#pragma mark - 下載成功 獲取下載內(nèi)容
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
//存儲本地
//1.獲取Documents文件夾路徑 (不要將視頻、音頻等較大資源存儲在Caches路徑下)
*方法一
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
*方法二
NSFileManager *manager = [NSFileManager defaultManager];
NSURL * documentsDirectory = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
//2.創(chuàng)建資源存儲路徑
NSString *appendPath = [NSString stringWithFormat:@"/new.mp4"];
NSString *file = [documentsPath stringByAppendingString:appendPath];
//3.將下載好的視頻資源存儲在路徑下
//刪除之前相同路徑的文件
BOOL remove = [manager removeItemAtPath:file error:nil];
//將視頻資源從原有路徑移動到自己指定的路徑
BOOL success = [manager copyItemAtPath:location.path toPath:file error:nil];
if (success) {
//回到主線程進(jìn)行本地視頻播放
dispatch_async(dispatch_get_main_queue(), ^{
//創(chuàng)建視頻播放的本地路徑
*** 請使用此方法創(chuàng)建本地路徑
NSURL *url = [[NSURL alloc]initFileURLWithPath:file];
*** 此方法創(chuàng)建的路徑無法播放 不是一個完整的路徑
//NSURL *url2 = [[NSURL alloc]initWithString:file];
//系統(tǒng)的視頻播放器
AVPlayerViewController *controller = [[AVPlayerViewController alloc]init];
//播放器的播放類
AVPlayer * player = [[AVPlayer alloc]initWithURL:url];
controller.player = player;
//自動開始播放
[controller.player play];
//推出視屏播放器
[self presentViewController:controller animated:YES completion:nil];
});
}
}
- NSURLSessionDownloadTask支持取消下載,可以在下載過程中隨時取消繼續(xù)下載,同時也可以實(shí)現(xiàn)恢復(fù)下載。
-
取消下載
cancelByProducingResumeData//用當(dāng)前NSURLSessionDownloadTask對象去調(diào)用取消下載 [self.downTask cancelByProducingResumeData: ^(NSData * _Nullable resumeData) { //全局變量 接收當(dāng)前下載的資源 self.data = resumeData; } //將當(dāng)前下載任務(wù)置為空 self.downTask = nil; -
恢復(fù)下載
downloadTaskWithResumeData//恢復(fù)下載 實(shí)際上是建立了一個新的下載任務(wù) 去繼續(xù)之前的下載 self.downTask = [self.downLoadSession downloadTaskWithResumeData:self.data]; //開啟任務(wù) [self.downTask resume]; }
-
自動緩存
上面講到的是自己去手動操控整個下載過程,那么,很多伙伴就會講這樣是不是太麻煩了。如果你了解了NSURLSession的緩存策略,那么,你就會發(fā)現(xiàn),我們這么寫確實(shí)是太麻煩了,那么下面我們就來學(xué)習(xí)一下NSURsession的自動緩存。
在開始之前,先介紹一下
NSURLRequestUseProtocolCachePolicy的幾種緩存策略:
NSURLRequestUseProtocolCachePolicy= 0, 默認(rèn)的緩存策略, 如果緩存不存在,直接從服務(wù)端獲取。如果緩存存在,
會根據(jù)response中的Cache-Control字段判斷下一步操作,如: Cache-Control字段為must-revalidata, 則詢問服務(wù)端該數(shù)據(jù)是否有更新,無更新的話直接返回給用戶緩存數(shù)據(jù),若已更新,則請求服務(wù)端.
NSURLRequestReloadIgnoringLocalCacheData= 1, 忽略本地緩存數(shù)據(jù),直接請求服務(wù)端.
NSURLRequestIgnoringLocalAndRemoteCacheData= 4, 忽略本地緩存,代理服務(wù)器以及其他中介,直接請求源服務(wù)端.
NSURLRequestReloadIgnoringCacheData= NSURLRequestReloadIgnoringLocalCacheData
NSURLRequestReturnCacheDataElseLoad= 2, 有緩存就使用,不管其有效性(即忽略Cache-Control字段), 無則請求服務(wù)端.
NSURLRequestReturnCacheDataDontLoad= 3, 死活加載本地緩存. 沒有就失敗. (確定當(dāng)前無網(wǎng)絡(luò)時使用).
7>
NSURLRequestReloadRevalidatingCacheData= 5, 緩存數(shù)據(jù)必須得得到服務(wù)端確認(rèn)有效才使用(貌似是NSURLRequestUseProtocolCachePolicy中的一種情況)
因此,我們可以根據(jù)自己的需求去設(shè)置不同的緩存策略,而默認(rèn)的就是如果有緩存就通過緩存獲取數(shù)據(jù),沒有緩存就去請求網(wǎng)絡(luò)數(shù)據(jù)。
這里,我們通過一個請求圖片的例子,來窺探一下神奇的自動緩存。
- 代碼:
//創(chuàng)建一個UIImageView+MyImageView.h的類目,
//在.h添加一個方法
- (void)loadIamgeWithURL:(NSString *)urlString
//在.m去實(shí)現(xiàn)此方法
- (void)loadIamgeWithURL:(NSString *)urlString
{
//創(chuàng)建下載圖片的url
NSURL *url = [NSURL URLWithString:urlString];
//創(chuàng)建網(wǎng)絡(luò)請求配置類
NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//創(chuàng)建網(wǎng)絡(luò)會話
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:[NSOperationQueue new]];
//創(chuàng)建請求并設(shè)置緩存策略以及超時時長
NSURLRequest *imgRequest = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:30.f];
//*也可通過configuration.requestCachePolicy 設(shè)置緩存策略
//創(chuàng)建一個下載任務(wù)
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:imgRequest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//下載完成后獲取數(shù)據(jù) 此時已經(jīng)自動緩存到本地,下次會直接從本地緩存獲取,不再進(jìn)行網(wǎng)絡(luò)請求
NSData * data = [NSData dataWithContentsOfURL:location];
//回到主線程
dispatch_async(dispatch_get_main_queue(), ^{
//設(shè)置圖片
self.image = [UIImage imageWithData:data];
});
}];
//啟動下載任務(wù)
[task resume];
}
通過這種緩存策略,我們就可以實(shí)現(xiàn)圖片下載并自動緩存,當(dāng)我們需要再次使用此資源的時候,它就會自動去本地緩存查找是否有已經(jīng)下載好的圖片資源,
如果有就會直接去本地的,從而不需要再去進(jìn)行網(wǎng)絡(luò)請求??梢栽谙螺d完成后,將網(wǎng)絡(luò)斷開進(jìn)行測試。
總結(jié)
本次主要是講解了NSURLSession的下載,以及自動緩存策略。它的功能非常強(qiáng)大,還有很多沒來得及細(xì)細(xì)研究,如果你也喜歡它??,那就抓緊時間去研究吧~