iOS - 關於NSURLCache

一、簡介

  • NSURLCache 爲應用的 URL 請求提供了內存以及磁盤上的綜合緩存機制,作爲基礎類庫 URL 加載的一部分,任何通過 NSURLConnection 加載的請求都將被 NSURLCache 處理。
  • 網絡緩存減少了需要向服務器發送請求的次數,同時也提升了離線或在低速網絡中使用應用的體驗。
  • 當一個請求完成下載來自服務器的迴應,一個緩存的迴應將在本地保存。下一次同一個請求再發起時,本地保存的迴應就會馬上返回,不需要連接服務器。NSURLCache
    自動透明 地返回迴應。
  • 爲了好好利用 NSURLCache
    ,你需要初始化並設置一個共享的 URL 緩存。在 iOS 中這項工作需要在 -application:didFinishLaunchingWithOptions:
    完成
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 
    diskCapacity:20 * 1024 * 1024
    diskPath:nil];
    [NSURLCache setSharedURLCache:URLCache];}
    緩存策略由請求(客戶端)和迴應(服務端)分別指定。理解這些策略以及它們如何相互影響,是爲您的應用程序找到最佳行爲的關鍵。

二、NSURLRequestCachePolicy

  • NSURLRequest 有個 cachePolicy 屬性,它根據以下常量指定了請求的緩存行爲:
    • NSURLRequestUseProtocolCachePolicy: 對特定的 URL 請求使用網絡協議中實現的緩存邏輯。這是默認的策略。
    • NSURLRequestReloadIgnoringLocalCacheData:數據需要從原始地址加載。不使用現有緩存。
    • NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅忽略本地緩存,同時也忽略代理服務器或其他中間介質目前已有的、協議允許的緩存。
    • NSURLRequestReturnCacheDataElseLoad:無論緩存是否過期,先使用本地緩存數據。如果緩存中沒有請求所對應的數據,那麼從原始地址加載數據。
    • NSURLRequestReturnCacheDataDontLoad:無論緩存是否過期,先使用本地緩存數據。如果緩存中沒有請求所對應的數據,那麼放棄從原始地址加載數據,請求視爲失敗(即:“離線”模式)。
    • NSURLRequestReloadRevalidatingCacheData:從原始地址確認緩存數據的合法性後,緩存數據就可以使用,否則從原始地址加載。

      注意

      NSURLRequestReloadIgnoringLocalAndRemoteCacheData
      和NSURLRequestReloadRevalidatingCacheData
      根本沒有實現Link to Radar)更加加深了混亂程度!

  • 關於 NSURLRequestCachePolicy
    ,以下才是你 實際 需要了解的東西:

    常量 -------------------------------意義
    UseProtocolCachePolicy------------- --默認行爲
    ReloadIgnoringLocalCacheData---------不使用緩存
    ReturnCacheDataElseLoad-------------使用緩存(不管它是否過期),如果緩存中沒有,那從網絡加載吧
    ReturnCacheDataDontLoad------------離線模式:使用緩存(不管它是否過期),但是從網絡加載
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData,NSURLRequestReloadRevalidatingCacheData根本沒有實現


三、HTTP 緩存語義

  • 因爲 NSURLConnection被設計成支持多種協議——包括 FTP、HTTP、HTTPS——所以 URL 加載系統用一種協議無關的方式指定緩存。爲了本文的目的,緩存用術語 HTTP 語義來解釋
  • HTTP 請求和迴應用 headers 來交換元數據,如字符編碼、MIME 類型和緩存指令等。
  • Request Cache Headers
    • 在默認情況下,NSURLRequest 會用當前時間決定是否返回緩存的數據。爲了更精確地控制,允許使用以下請求頭:
      • If-Modified-Since- 這個請求頭與 Last-Modified 迴應頭相對應。把這個值設爲同一終端最後一次請求時返回的 Last-Modified 字段的值。
      • If-None-Match - 這個請求頭與與 Etag 迴應頭相對應。使用同一終端最後一次請求的 Etag 值。
  • Response Cache Headers
    • NSHTTPURLResponse 包含多個 HTTP 頭,當然也包括以下指令來說明迴應應當如何緩存:
      • Cache-Control - 這個頭 必須由服務器端 指定以開啓客戶端的 HTTP 緩存功能。這個頭的值可能包含 max-age(緩存多久),是公共 public 還是私有 private,或者不緩存no-cache 等信息。詳情請參閱 Cache-Control section of RFC 2616
    • 除了 Cache-Control 以外,服務器也可能發送一些附加的頭用於根據需要有條件地請求(如上一節所提到的)
      • Last-Modified - 這個頭的值表明所請求的資源上次修改的時間。例如,一個客戶端請求最近照片的時間線,/photos/timeline,Last-Modified 的值可以是最近一張照片的拍攝時間。
      • Etag - 這是 “entity tag” 的縮寫,它是一個表示所請求資源的內容的標識符。在實踐中,Etag 的值可以是類似於資源的 MD5 之類的東西。這對於那些動態生成的、可能沒有明顯的 Last-Modified
        值的資源非常有用。
  • NSURLConnectionDelegate
    • 一旦收到了服務器的迴應,NSURLConnection 的代理就有機會在 -connection:willCacheResponse: 中指定緩存數據。
    • NSCachedURLResponse 是個包含 NSURLResponse 以及它對應的緩存中的 NSData 的類.
    • 在 -connection:willCacheResponse: 中,cachedResponse 對象會根據 URL 連接返回的結果自動創建。因爲 NSCachedURLResponse 沒有可變部分,爲了改變 cachedResponse 中的值必須構造一個新的對象,把改變過的值傳入 –initWithResponse:data:userInfo:storagePolicy:,例如:
      - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
      { NSMutableDictionary *mutableUserInfo = [[cachedResponse userInfo] mutableCopy]; 
      NSMutableData *mutableData = [[cachedResponse data] mutableCopy];
      NSURLCacheStoragePolicy storagePolicy = NSURLCacheStorageAllowedInMemoryOnly; 
      // ...
      return [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response] 
      data:mutableData 
      userInfo:mutableUserInfo
      storagePolicy:storagePolicy];
      }
      如果 -connection:willCacheResponse: 返回 nil,迴應將不會緩存。
      - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
      {
      return nil;
      }
      如果不實現此方法,NSURLConnection 就簡單地使用本來要傳入 -connection:willCacheResponse:的那個緩存對象,所以除非你需要改變一些值或者阻止緩存,否則這個代理方法不必實現。


文/Mitchell(簡書作者)
原文鏈接:http://www.jianshu.com/p/227f8a5506fa
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章