iOS 網路請求資料快取

有稜角的圓發表於2016-08-16

1. NSURLCache簡介:

iOS對NSURLRequest提供了7種快取策略:(實際上能用的只有4種)

NSURLRequestUseProtocolCachePolicy // 預設的快取策略(取決於協議)

NSURLRequestReloadIgnoringLocalCacheData // 忽略快取,重新請求

NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現

NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略快取,重新請求

NSURLRequestReturnCacheDataElseLoad// 有快取就用快取,沒有快取就重新請求

NSURLRequestReturnCacheDataDontLoad// 有快取就用快取,沒有快取就不發請求,當做請求出錯處理(用於離線模式)

NSURLRequestReloadRevalidatingCacheData // 未實現

 

NSURLCache的常見用法

(1)獲得全域性快取物件(沒必要手動建立)NSURLCache *cache = [NSURLCache sharedURLCache]; 

(2)設定記憶體快取的最大容量(位元組為單位,預設為512KB)- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

(3)設定硬碟快取的最大容量(位元組為單位,預設為10M)- (void)setDiskCapacity:(NSUInteger)diskCapacity;

(4)硬碟快取的位置:沙盒/Library/Caches

(5)取得某個請求的快取- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; 

(6)清除某個請求的快取- (void)removeCachedResponseForRequest:(NSURLRequest *)request;

(7)清除所有的快取- (void)removeAllCachedResponses;

 快取GET請求

  要想對某個GET請求進行資料快取,非常簡單

  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

  // 設定快取策略

  request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

  只要設定了快取策略,系統會自動利用NSURLCache進行資料快取

 

 快取的注意事項

快取的設定需要根據具體的情況考慮,如果請求某個URL的返回資料:

  (1)經常更新:不能用快取!比如股票、彩票資料

  (2)一成不變:果斷用快取

  (3)偶爾更新:可以定期更改快取策略 或者 清除快取

提示:如果大量使用快取,會越積越大,建議定期清除快取

 2.藉助ETag或Last-Modified判斷檔案快取是否有效

 通過列印一個response例項,可以看到response header部分如下所示:

 我們可以在請求資料時先上傳Etag或者是Last-Modified讓伺服器端進行判斷,若資料未發生變動則載入本地資料,否則載入伺服器端資料。

請求的HeaderValue和響應的HeaderValue如下所示:

 

下面以Etag為例進行資料快取:

先設定快取記憶體和硬碟大小:

NSURLCache *urlCache= [[NSURLCache alloc]initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
    
    [NSURLCache setSharedURLCache:urlCache];

下載一張圖片:

- (IBAction)download:(UIButton *)sender {
    
    NSURL *url=[NSURL URLWithString:@"http://192.168.1.102:8080/love/images/bg2.jpg"];
    NSMutableURLRequest *mRequest=[NSMutableURLRequest requestWithURL:url];
    mRequest.cachePolicy=NSURLRequestReloadIgnoringCacheData;
    mRequest.timeoutInterval=5;
    // 根據請求獲取到`被快取的響應`!
    NSCachedURLResponse *cacheResponse =  [[NSURLCache sharedURLCache] cachedResponseForRequest:mRequest];
    //cacheResponse不存在時設定etag為空
    if (!cacheResponse) {
        self.etag=nil;
    }
    //傳送etag
    if (self.etag.length>0) {
        //NSLog(@"Etag=%@",self.etag);
        [mRequest setValue:self.etag forHTTPHeaderField:@"If-None-Match"];
    }
    
        [NSURLConnection sendAsynchronousRequest:mRequest queue:[NSOperationQueue new] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
            // 型別轉換(如果將父類設定給子類,需要強制轉換)
            NSHTTPURLResponse *httpResponse=(NSHTTPURLResponse*)response;
           // NSLog(@"res=%@",httpResponse);
            // 判斷響應的狀態碼是否是 304 Not Modified (更多狀態碼含義解釋: https://github.com/ChenYilong/iOSDevelopmentTips
            if (httpResponse.statusCode==304) {
                NSLog(@"載入本地快取圖片");
                // 如果是,使用本地快取
                // 根據請求獲取到`被快取的響應`!
                NSCachedURLResponse *cacheResponse =  [[NSURLCache sharedURLCache] cachedResponseForRequest:mRequest];
                // 拿到快取的資料
                data = cacheResponse.data;
                
            }else{
                
                NSLog(@"請求網路端圖片");
            }
            
            if(data){
                
                [self performSelectorOnMainThread:@selector(setImage:) withObject:data waitUntilDone:YES];
            }
            
             self.etag=httpResponse.allHeaderFields[@"Etag"];
            
        }];
    
    

  //  NSArray *arr=NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
  //  NSString *path=[arr objectAtIndex:0];
   // NSLog(@"%@",path);
}

-(void)setImage:(NSData*)data{
   // NSLog(@"setimage");
     self.imageView.image=[UIImage imageWithData:data];
}

清除所有快取:

- (IBAction)clearCache:(UIButton *)sender {
    
    [[NSURLCache sharedURLCache] removeAllCachedResponses];

}

 

 

 

 

 

參考文獻:

http://www.jianshu.com/p/fb5aaeac06ef

http://www.cnblogs.com/wendingding/p/3950198.html

相關文章