iOS 網(wǎng)絡(luò)緩存


常見(jiàn)的網(wǎng)絡(luò)數(shù)據(jù)緩存方式

GET網(wǎng)絡(luò)請(qǐng)求緩存

概述

首先要知道骂际,POST請(qǐng)求不能被緩存焦影,只有 GET 請(qǐng)求能被緩存鳞绕。緩存的思路就是將查詢的參數(shù)組成的值作為 key ,對(duì)應(yīng)結(jié)果作為value氧急。從這個(gè)意義上說(shuō),一個(gè)文件的資源鏈接岂座,也叫 GET 請(qǐng)求

該怎么做?

前提

針對(duì)的是get請(qǐng)求

針對(duì)的是get請(qǐng)求

針對(duì)的是get請(qǐng)求

NSURLCache : NSURLCache 為您的應(yīng)用的 URL 請(qǐng)求提供了內(nèi)存中以及磁盤上的綜合緩存機(jī)制杭措。 作為基礎(chǔ)類庫(kù) URL 加載系統(tǒng) 的一部分费什,任何通過(guò) NSURLConnection 加載的請(qǐng)求都將被 NSURLCache 處理。個(gè)默認(rèn)緩存在內(nèi)存手素,并且可以通過(guò)一些配置操作可以持久緩存到磁盤的類鸳址。

那么知道了這些之后開始我們的步驟

設(shè)置NSURLCache的大小時(shí),大多使用下面的代碼
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
    [NSURLCache setSharedURLCache:urlCache];
}
設(shè)置一個(gè)緩存策略

無(wú)論你是用的是NSURLRequest還是NSMutableURLRequest泉懦,你都需要去設(shè)置一下它們的cachePolicy屬性

typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
    NSURLRequestUseProtocolCachePolicy = 0,

    NSURLRequestReloadIgnoringLocalCacheData = 1,
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
    NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,

    NSURLRequestReturnCacheDataElseLoad = 2,
    NSURLRequestReturnCacheDataDontLoad = 3,

    NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
}

這些緩存都代表什么意思呢稿黍?

NSURLRequestUseProtocolCachePolicy: 對(duì)特定的 URL 請(qǐng)求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯。這是默認(rèn)的策略崩哩。
NSURLRequestReloadIgnoringLocalCacheData:數(shù)據(jù)需要從原始地址加載巡球。不使用現(xiàn)有緩存。
NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅忽略本地緩存邓嘹,同時(shí)也忽略代理服務(wù)器或其他中間介質(zhì)目前已有的酣栈、協(xié)議允許的緩存。
NSURLRequestReturnCacheDataElseLoad:無(wú)論緩存是否過(guò)期汹押,先使用本地緩存數(shù)據(jù)矿筝。如果緩存中沒(méi)有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù),那么從原始地址加載數(shù)據(jù)棚贾。
NSURLRequestReturnCacheDataDontLoad:無(wú)論緩存是否過(guò)期窖维,先使用本地緩存數(shù)據(jù)。如果緩存中沒(méi)有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù)妙痹,那么放棄從原始地址加載數(shù)據(jù)铸史,請(qǐng)求視為失敗(即:“離線”模式)怯伊。
NSURLRequestReloadRevalidatingCacheData:從原始地址確認(rèn)緩存數(shù)據(jù)的合法性后沛贪,緩存數(shù)據(jù)就可以使用,否則從原始地址加載

知道了它們的意思之后我把工程中加入了下面的代碼

if (![Global shareInstance].isNetReachable) {
            request.cachePolicy = NSURLRequestReturnCacheDataDontLoad;
        }else{
            request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
        }

這樣就做到了當(dāng)網(wǎng)絡(luò)不通時(shí)使用本地緩存利赋。當(dāng)有網(wǎng)絡(luò)是則先使用本地緩存,如果找不到本地緩存就去加載數(shù)據(jù)媚送。
但有些場(chǎng)景下我們的緩存是存在時(shí)效性的。比如商品詳情不同的時(shí)間返回的價(jià)格因?yàn)橛谢顒?dòng)價(jià)已經(jīng)不同了寇甸。那么此時(shí)這種辦法就明顯不適用了疗涉。

控制緩存的有效性

借助ETag或者Las-Modified判斷文件是否有效

ETag

HTTP協(xié)議規(guī)格說(shuō)明定義ETag為“被請(qǐng)求變量的實(shí)體值”吟秩。另一種說(shuō)法是,ETag是一個(gè)可以與Web資源關(guān)聯(lián)的記號(hào)(token)涵防。Web資源可以是一個(gè)web頁(yè)面、json或xml數(shù)據(jù)壮池、文件等偏瓤。Etag有點(diǎn)類似于文件hash或者說(shuō)是信息摘要厅克。
在瀏覽器默認(rèn)的行為中,當(dāng)進(jìn)行一次URL請(qǐng)求橙依,服務(wù)端會(huì)返回'Etag'響應(yīng)頭,下次瀏覽器請(qǐng)求相同的URL時(shí)窗骑,瀏覽器會(huì)自動(dòng)將它設(shè)置為請(qǐng)求頭'If-None-Match'的值褪储。服務(wù)器收到這個(gè)請(qǐng)求之后,就開始做信息校驗(yàn)工作將自己本次產(chǎn)生的Etag與請(qǐng)求傳遞過(guò)來(lái)的'If-None-Match'對(duì)比慧域,如果相同鲤竹,則返回HTTP狀態(tài)碼304,并且response數(shù)據(jù)體中沒(méi)有數(shù)據(jù)昔榴。
具體的使用看下面代碼例子

- (void)getData:(GetDataCompletion)completion {
    NSURL *url = [NSURL URLWithString:kETagImageURL];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];
    
    // 發(fā)送 etag
    if (self.etag.length > 0) {
        [request setValue:self.etag forHTTPHeaderField:@"If-None-Match"];
    }
    
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        
        // NSLog(@"%@ %tu", response, data.length);
        // 類型轉(zhuǎn)換(如果將父類設(shè)置給子類辛藻,需要強(qiáng)制轉(zhuǎn)換)
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        NSLog(@"statusCode == %@", @(httpResponse.statusCode));
        // 判斷響應(yīng)的狀態(tài)碼是否是 304 Not Modified (更多狀態(tài)碼含義解釋: https://github.com/ChenYilong/iOSDevelopmentTips)
        if (httpResponse.statusCode == 304) {
            NSLog(@"加載本地緩存圖片");
            // 如果是,使用本地緩存
            // 根據(jù)請(qǐng)求獲取到`被緩存的響應(yīng)`互订!
            NSCachedURLResponse *cacheResponse =  [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
            // 拿到緩存的數(shù)據(jù)
            data = cacheResponse.data;
        }
        
        // 獲取并且紀(jì)錄 etag吱肌,區(qū)分大小寫
        self.etag = httpResponse.allHeaderFields[@"Etag"];
        
        NSLog(@"etag值%@", self.etag);
        !completion ?: completion(data);
    }];
}

Last-Modified

Last-Modified值在服務(wù)器處理階段代表著文件的上次修改時(shí)間,在處理結(jié)束后作為一個(gè)響應(yīng)頭放到response中仰禽。如果在請(qǐng)求中添加了'If-Modified-Since'頭氮墨,并將這個(gè)值設(shè)置為上次請(qǐng)求時(shí)得到的響應(yīng)頭'Last-Modified'的值,那么這次請(qǐng)求服務(wù)器中邏輯的偽代碼

if ETag != 請(qǐng)求頭中的'If-Non-Match' || 查詢到的'Last-Modified'(上次修改的時(shí)間) != 請(qǐng)求頭中的'If-Modified-Since'
    返回的response狀態(tài)碼200 和 數(shù)據(jù)
else
   返回的reponse狀態(tài)碼304

目前這些也是個(gè)人通過(guò)學(xué)習(xí)網(wǎng)上文章的理解吐葵,待之后實(shí)踐后再來(lái)補(bǔ)充詳細(xì)理解规揪。

關(guān)于ETag和Last-Modified的詳細(xì)說(shuō)明可以看下面兩邊詳細(xì)講解


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市温峭,隨后出現(xiàn)的幾起案子猛铅,更是在濱河造成了極大的恐慌,老刑警劉巖凤藏,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奸忽,死亡現(xiàn)場(chǎng)離奇詭異堕伪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)栗菜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門欠雌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人疙筹,你說(shuō)我怎么就攤上這事富俄。” “怎么了腌歉?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蛙酪,是天一觀的道長(zhǎng)齐苛。 經(jīng)常有香客問(wèn)我翘盖,道長(zhǎng),這世上最難降的妖魔是什么凹蜂? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任馍驯,我火速辦了婚禮,結(jié)果婚禮上玛痊,老公的妹妹穿的比我還像新娘汰瘫。我一直安慰自己,他們只是感情好擂煞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著对省,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哀托。 梳的紋絲不亂的頭發(fā)上劳秋,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天玻淑,我揣著相機(jī)與錄音,去河邊找鬼辛慰。 笑死干像,一個(gè)胖子當(dāng)著我的面吹牛驰弄,可吹牛的內(nèi)容都是我干的戚篙。 我是一名探鬼主播溺职,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浪耘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了痛倚?” 一聲冷哼從身側(cè)響起澜躺,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掘鄙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后收津,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撞秋,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡部服,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年廓八,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赵抢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宠叼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冒冬,到底是詐尸還是另有隱情,我是刑警寧澤剂邮,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布挥萌,位于F島的核電站枉侧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏憨栽。R本人自食惡果不足惜辆影,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一黍特、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧次慢,春花似錦翔曲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至猾蒂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舔箭,已是汗流浹背蚊逢。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工箫章, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炉抒,地道東北人稚叹。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓扒袖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親季率。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容