最近由于對NSURLRequestCachePolicy設(shè)置不當(dāng),導(dǎo)致了版本中出現(xiàn)一些bug,特此對NSURLRequestCachePolicy進行了一些研究
NSURLRequestCachePolicy的定義如下
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
NSURLRequestUseProtocolCachePolicy = 0,
NSURLRequestReloadIgnoringLocalCacheData = 1,
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2,
NSURLRequestReturnCacheDataDontLoad = 3,
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
NSURLRequestUseProtocolCachePolicy
默認(rèn)的緩存策略,其行為是由協(xié)議指定的針對該協(xié)議最好的實現(xiàn)方式。關(guān)于該策略的介紹,篇后詳細(xì)說明。NSURLRequestReloadIgnoringCacheData
從服務(wù)端加載數(shù)據(jù),完全忽略緩存。NSURLRequestReturnCacheDataElseLoad
使用緩存數(shù)據(jù),忽略其過期時間;只有在沒有緩存版本的時候才從源端加載數(shù)據(jù)。NSURLRequestReturnCacheDataDontLoad
只使用cache數(shù)據(jù),如果不存在cache,請求失??;用于沒有建立網(wǎng)絡(luò)連接離線模式
NSURLRequestUseProtocolCachePolicy實現(xiàn)機制
蘋果官方提供的決策樹如下:

由圖中可以看出,簡單流程如下:
- 如果請求的緩存響應(yīng)不存在,則URL加載系統(tǒng)直接從源端加載數(shù)據(jù);
- 否則,如果緩存響應(yīng)中沒有明確表示每次請求必須重新驗證,則如果不是響應(yīng)的緩存過期了,則URL加載系統(tǒng)會返回緩存數(shù)據(jù)
- 如果緩存的響應(yīng)過期或者需要重新驗證,URL加載系統(tǒng)發(fā)送
HEAD請求到源端,查看資源是否發(fā)生了變化。如果變化了,則URL加載系統(tǒng)取出從始發(fā)源的數(shù)據(jù)。否則,它返回緩存的響應(yīng)。
緩存的響應(yīng)過期或者需要重新驗證說明
對于緩存的響應(yīng)過期或者需要重新驗證的情況,可以通過HTTP中請求和響應(yīng)頭來判斷
- Cache-Control
在第一次請求到服務(wù)器資源的時候,服務(wù)器需要使用Cache-Control這個響應(yīng)頭來指定緩存策略,它的格式如下:Cache-Control:max-age=xxxx,這個頭指指明緩存過期的時間
Cache-Control頭具有如下選項:
| 常量 | 意義 |
|---|---|
| public | 指示響應(yīng)可被任何緩存區(qū)緩存 |
| private | 內(nèi)容只緩存到私有緩存中(僅客戶端可以緩存) |
| no-cache | 指示請求或響應(yīng)消息不能緩存 |
| no-store | 所有內(nèi)容都不會被緩存到緩存或 Internet 臨時文件中 |
| must-revalidation | 如果緩存的內(nèi)容失效,請求必須發(fā)送到服務(wù)器進行重新驗證 |
| max-age | 可以接收生存期不大于指定時間(以秒為單位)的響應(yīng) |
| min-fresh | 可以接收響應(yīng)時間小于當(dāng)前時間加上指定時間的響應(yīng) |
| max-stale | 可以接收超出超時期間的響應(yīng)消息 |
Expires
Expires表示存在時間,允許客戶端在這個時間之前不去檢查(發(fā)請求),等同max-age的效果。但是如果同時存在,則被Cache-Control的max-age覆蓋。
格式:Expires = "Expires" ":" HTTP-date"
例如:Expires: Thu, 01 Dec 1994 16:00:00 GMT (必須是GMT格式)Last-Modified/If-Modified-Since
Last-Modified是由服務(wù)器返回響應(yīng)頭,標(biāo)識資源的最后修改時間.
If-Modified-Since則由客戶端發(fā)送,標(biāo)識客戶端所記錄的,資源的最后修改時間。服務(wù)器接收到帶有該請求頭的請求時,會使用該時間與資源的最后修改時間進行對比,如果發(fā)現(xiàn)資源未被修改過,則直接返回HTTP 304而不返回包體,告訴客戶端直接使用本地的緩存。否則響應(yīng)完整的消息內(nèi)容。Etag/If-None-Match
Etag由服務(wù)器發(fā)送,告之當(dāng)資源在服務(wù)器上的一個唯一標(biāo)識符。
客戶端請求時,如果發(fā)現(xiàn)資源過期(使用Cache-Control的max-age),發(fā)現(xiàn)資源具有Etag聲明,這時請求服務(wù)器時則帶上If-None-Match頭,服務(wù)器收到后則與資源的標(biāo)識進行對比,決定返回200或者304。