iOS 網路請求快取:NSURLCache詳解

發表於2016-12-12

我讀過一些開源專案的網路請求快取的程式碼,基本上都是採用在本地存檔案的方式進行快取。如果你打算在你的專案中加入網路請求的快取,可能你並不需要自己造一個輪子,瞭解一下NSURLCache就足夠。

這是一個Apple已經為你準備好了的網路請求快取類。網上對這個類的介紹並不多,並且有的文章講得很不詳細。希望這篇文章能讓你對NSURLCache有一個比較詳細的瞭解。

快取

首先,NSURLCache提供的是記憶體以及磁碟的綜合快取機制。許多文章談到,使用NSURLCache之前需要在AppDelegate中快取空間的設定:

然而如果你不新增上面的程式碼,並且執行如下程式碼,可以看到:

也就是說,其實預設就已經設定好了512kb的記憶體快取空間,以及10MB的磁碟快取空間。可能你的程式碼中並沒有寫任何與NSURLCache有關的東西,但其實它已經默默的開始幫你進行快取了。

已經快取上了,但是怎麼使用快取呢?請繼續往下。

快取策略

GET

不用多說,NSURLCache只會對你的GET請求進行快取。

NSURLRequestCachePolicy

NSURLRequest中有個屬性:

你可以通過這個屬性來設定請求的快取策略,

其實其他幾個值都比較好理解,唯獨預設值UseProtocolCachePolicy讓我不太懂。

字面上的意思是按照協議的快取策略進行快取,那麼這是什麼協議呢?http協議

詳細:RFC 2616, Section 13

伺服器返回的響應頭中會有這樣的欄位:Cache-Control: max-age or Cache-Control: s- maxage,通過Cache-Control來指定快取策略,max-age來表示過期時間。根據這些欄位快取機制再採用如下策略:

  • 如果本地沒有快取資料,則進行網路請求。
  • 如果本地有快取,並且快取沒有失效,則使用快取。
  • 如果快取已經失效,則詢問伺服器資料是否改變,如果沒改變,依然使用快取,如果改變了則請求新資料。
  • 如果沒有指定是否失效,那麼系統將自己判斷快取是否失效。(通常認為是6-24小時的有效時間)

其實我以前對Cache-Control之類的也並不太瞭解 T_T,自己默默的print了一下響應頭,你可以看到:

這也就是為什麼,雖然NSURLCache一直在默默的快取,但是我並沒有感受到,當然或許你那裡不一樣。這個no-cache就表示不快取。

這裡要額外提一句,看到網上有同學說自己出現了某個請求資料一直使用快取,沒有被更新。這種情況可能就是伺服器返回的Cache-Control有誤。

開啟沙盒路徑下的Library/Caches 中,你可以看到快取檔案:

ca10144bb74a4b98f8a8ed435640e5f3
沙盒中的快取檔案.png

這可以說明存在磁碟上的資料是存在資料庫裡的,效能不用擔心。開啟資料庫檔案就可以看到請求的資料。

a8e70d2e1d3255127addf221c9643ff7
快取資料.png

cfurl_cache_response表中可以看到有一個欄位是request_key,通過裡面的值可以推斷每一個response是通過請求的url+引數來作為key儲存的。

當然,經過我的多次試驗,在Cache-Control: no-cache的情況下,NSURLCache也會進行快取,但是並不使用快取資料。

總結一下:預設情況下NSURLCache的快取策略是根據http協議來的,伺服器通過Cache-Control: max-age欄位來告訴NSURLCache是否需要快取資料。

快取封裝

如果你不打算採用http協議的快取策略,依然可以使用NSURLCache進行快取。

你可以通過這個方法,傳入請求,來獲取快取。NSCachedURLResponse儲存了上次請求的資料以及響應頭。

NSURLSessionDelegate協議中有如下方法,可以對即將快取的資料進行修改,新增userInfo,在代理方法中必須呼叫completionHandler,傳入將要快取的資料,如果傳nil則表示不快取。

Alamofire中可以這樣寫:

參考

我的blog:Roxily’s Blog

我也只是簡單的對NSURLCache進行了介紹,需要深入瞭解的話大家還是需要拜讀一下文章,希望能給大家一些幫助:

相關文章