NSURLSession下載與緩存

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的幾種緩存策略:

  1. NSURLRequestUseProtocolCachePolicy = 0, 默認(rèn)的緩存策略, 如果緩存不存在,直接從服務(wù)端獲取。如果緩存存在,
    會(huì)根據(jù)response中的Cache-Control字段判斷下一步操作,如: Cache-Control字段為must-revalidata, 則詢問服務(wù)端該數(shù)據(jù)是否有更新,無更新的話直接返回給用戶緩存數(shù)據(jù),若已更新,則請求服務(wù)端.
  1. NSURLRequestReloadIgnoringLocalCacheData = 1, 忽略本地緩存數(shù)據(jù),直接請求服務(wù)端.
  1. NSURLRequestIgnoringLocalAndRemoteCacheData = 4, 忽略本地緩存,代理服務(wù)器以及其他中介,直接請求源服務(wù)端.
  1. NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData
  1. NSURLRequestReturnCacheDataElseLoad = 2, 有緩存就使用,不管其有效性(即忽略Cache-Control字段), 無則請求服務(wù)端.
  1. 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í)間去研究吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容