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