iOS的web緩存相關(guān)

背景

最近關(guān)于web界面偶有反饋拉到舊的界面股冗,導(dǎo)致出現(xiàn)一些異常情況;
因此和蚪,對web資源的加載止状、緩存進(jìn)行一些梳理。

正文

一攒霹、緩存相關(guān)概念介紹

  • NSURLCache是iOS系統(tǒng)常用的web緩存方式怯疤,通過[NSURLCache sharedURLCache]獲取默認(rèn)的緩存相關(guān)信息;可以在啟動的時候催束,通過[NSURLCache setSharedURLCache:URLCache]的方式設(shè)置一個自定義的NSURLCache集峦。

  • NSCache和NSURLCache名字相近,其實(shí)沒有什么關(guān)系抠刺;NSCache可以認(rèn)為是一個字典緩存塔淤,在內(nèi)存不足的時候會自動釋放對象。雖然是系統(tǒng)提供的官方緩存類速妖,但是實(shí)際開發(fā)中并沒有使用凯沪,替代者是YYCache。

  • URLProtocol是iOS系統(tǒng)對URL請求行為進(jìn)行抽象买优,細(xì)化出每一步操作妨马,讓開發(fā)者可以針對每一步進(jìn)行代理挺举,實(shí)現(xiàn)對特定請求的攔截,并返回本地的數(shù)據(jù)烘跺。
    使用的時候湘纵,首先通過canInitWithRequest:(NSURLRequest *)request,告訴系統(tǒng)要進(jìn)行代理滤淳;
    然后在startLoading中梧喷,通過判斷request和本地緩存信息,判斷本次請求是否可以返回本地數(shù)據(jù)脖咐,并相應(yīng)調(diào)用client的方法铺敌;
    舉例,下面就是讀取本地數(shù)據(jù)屁擅,判斷ETag是否相同偿凭,進(jìn)而返回304的邏輯:

NSString *requestETag = request.allHTTPHeaderFields[@"If-None-Match"];
NSString *etag = localData.eTag?:@"";
NSDictionary *headerFields = @{@"Cache-Control" : @"max-age=600", @"ETag":etag, @"Access-Control-Allow-Origin" : @"*"};
if (requestETag.length > 0 && [requestETag isEqualToString:etag]) {
    NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:304 HTTPVersion:nil headerFields:headerFields];  
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
    [self.client URLProtocolDidFinishLoading:self];
}

NSURLCache和URLProtocol的差別:
1、NSURLCache只支持GET請求派歌,URLProtocol還支持Post請求弯囊;
2、NSURLCache清理緩存通常使用removeAllCachedResponses清理全部緩存胶果,URLProtocol是代理資源加載過程匾嘱,本地磁盤的資源存儲由業(yè)務(wù)控制;

二早抠、HTTP的緩存機(jī)制

以某個web界面加載為例霎烙,當(dāng)我們不使用瀏覽器緩存時,返回的response是完整的html文本蕊连,同時還附帶著ETag吼过;


如果打開緩存策略,則請求頭帶了If-None-Match(對應(yīng)直接的ETag: "5e58f3dd-b0b")咪奖,此時回包體積明顯變小,同時返回碼是304酱床;


當(dāng)請求或者response帶有no-cache羊赵、max-age=0時,緩存的資源仍可使用扇谣,但是會通過請求進(jìn)行驗(yàn)證昧捷,類似上面的ETag,返回304表示Not Modified罐寨,可以繼續(xù)使用靡挥;(no-cache,并非放棄緩存

而當(dāng)max-age=3600時鸯绿,表示資源有效時間是1個小時跋破,在有效時間內(nèi)不需要通過后端驗(yàn)證簸淀,此時不需要發(fā)起網(wǎng)絡(luò)請求,會直接由cache返回數(shù)據(jù)毒返。(前提是客戶端的request的header租幕,沒有設(shè)置no-cache和max-age=0)

一個資源的請求流程:


圖源網(wǎng)絡(luò),侵刪

關(guān)于request和response的總結(jié):

  • request的header是資源請求的核心控制參數(shù)拧簸,如果request的cache策略是no-cache或者max-age=0劲绪,則一定會驗(yàn)證資源;
  • request沒有設(shè)置cache-control的策略盆赤,則按照response的策略進(jìn)行贾富,如果age大于reponse的max-age或者response設(shè)置了no-cache,則會進(jìn)行資源校驗(yàn)牺六;如果reponse設(shè)置了max-age=x颤枪,客戶端的age當(dāng)前小于x,則不會發(fā)起網(wǎng)絡(luò)請求兔乞,直接使用cache的數(shù)據(jù)汇鞭;

web同學(xué)表示,web界面通常不會設(shè)置request的cache-control庸追,因?yàn)殪o態(tài)資源的加載永遠(yuǎn)在js之前霍骄;
即使是在html的最前面加上cache-control的<meta>標(biāo)簽,也是在html拉到之后才能生效淡溯;
(但是客戶端開發(fā)可以設(shè)置request-header)

三读整、業(yè)務(wù)緩存邏輯(web緩存SDK)

在前面的client->cache->server基礎(chǔ)上,web緩存SDK所在的層級是在cache和server之間咱娶;
cache屬于瀏覽器自身的緩存米间,web緩存SDK相當(dāng)于代理,阻斷了瀏覽器發(fā)起的網(wǎng)絡(luò)請求膘侮,如果本地有匹配的數(shù)據(jù)屈糊,則使用本地數(shù)據(jù)返回,如果沒有使用網(wǎng)絡(luò)請求琼了,最終所有的數(shù)據(jù)都會加載到cache逻锐;
web緩存SDK和上面的緩存策略并沒有關(guān)系,上面的緩存策略決定是否要發(fā)起網(wǎng)絡(luò)請求去驗(yàn)證資源雕薪、加載資源昧诱,而web緩存SDK則是在請求發(fā)起之后直接返回,類似charles的map local所袁;

一張圖更好的來描述

四盏档、一個歷史教訓(xùn)

線上的web界面出現(xiàn)一個bug,web的同學(xué)修復(fù)完之后燥爷,手動刷新了cdn的資源和業(yè)務(wù)緩存SDK的資源蜈亩。
但是部分html配置的no-cache失效(設(shè)置了max-age=xxx)懦窘,導(dǎo)致如果之前進(jìn)入過在拉到之前,會使用瀏覽器緩存勺拣;導(dǎo)致本次啟動會一直使用舊的的界面奶赠。
解決方案:
1、更換該界面的url药有,使得cache失效毅戈;
2、清除webKit的緩存愤惰;

[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate dateWithTimeIntervalSince1970:0] completionHandler:^{
//清除靜態(tài)資源成功
    }];

總結(jié)

HTTP協(xié)議的學(xué)問博大精深苇经,這次借此對緩存相關(guān)知識進(jìn)行一次梳理。
如有紕漏宦言,歡迎指正扇单;如有關(guān)于緩存的使用建議,歡迎交流奠旺。
參考鏈接
https://stackoverflow.com/questions/27105094/how-to-remove-cache-in-wkwebview

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜘澜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子响疚,更是在濱河造成了極大的恐慌鄙信,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忿晕,死亡現(xiàn)場離奇詭異装诡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)践盼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鸦采,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咕幻,你說我怎么就攤上這事渔伯。” “怎么了肄程?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵锣吼,是天一觀的道長。 經(jīng)常有香客問我绷耍,道長,這世上最難降的妖魔是什么鲜侥? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任褂始,我火速辦了婚禮,結(jié)果婚禮上描函,老公的妹妹穿的比我還像新娘崎苗。我一直安慰自己狐粱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布胆数。 她就那樣靜靜地躺著肌蜻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪必尼。 梳的紋絲不亂的頭發(fā)上蒋搜,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音判莉,去河邊找鬼豆挽。 笑死,一個胖子當(dāng)著我的面吹牛券盅,可吹牛的內(nèi)容都是我干的帮哈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锰镀,長吁一口氣:“原來是場噩夢啊……” “哼娘侍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泳炉,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤憾筏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胡桃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踩叭,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年翠胰,在試婚紗的時候發(fā)現(xiàn)自己被綠了容贝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡之景,死狀恐怖斤富,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锻狗,我是刑警寧澤满力,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站轻纪,受9級特大地震影響油额,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刻帚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一潦嘶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崇众,春花似錦掂僵、人聲如沸航厚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幔睬。三九已至,卻和暖如春芹扭,著一層夾襖步出監(jiān)牢的瞬間麻顶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工冯勉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澈蚌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓灼狰,卻偏偏與公主長得像宛瞄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子交胚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355