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