NSURLCache緩存的位置

前言

對(duì)于NSURLRequest,我們都很熟悉。在創(chuàng)建request時(shí),可以設(shè)置屬性cachePolicy,決定從本地還是網(wǎng)絡(luò)上獲取內(nèi)容。那么如果是從本地取的話,是從哪取呢?下面來(lái)簡(jiǎn)單聊一下。

NSURLCahe

NSURLCahe實(shí)現(xiàn)了response的緩存機(jī)制,將NSURLRequest和NSCachedURLResponse映射起來(lái)。默認(rèn)情況下,Memory cache=4M,Disk cache=20M??梢宰宇惢疦SURLCahe實(shí)現(xiàn)自己的緩存邏輯。

如果response的httpHeader里Cache-control/expires設(shè)置為可以被緩存,iOS會(huì)自動(dòng)的將其存到本地?cái)?shù)據(jù)庫(kù)中。路徑是沙盒路徑下Library/Caches/bundid/Cache.db。,對(duì)于webview的緩存,也一樣,因?yàn)樗彩怯玫腘SURLCache。

1.png

NSCachedURLResponse

NSCachedURLResponse是包含了NSURLResponse和緩存data的類。當(dāng)數(shù)據(jù)返回時(shí),將要緩存時(shí)會(huì)調(diào)這個(gè)方法。如果返回nil,則不緩存。原理如下。

- (nullable NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)cachedResponse;

    if ([connection currentRequest].cachePolicy == NSURLRequestUseProtocolCachePolicy) {
        NSDictionary *headers = [httpResponse allHeaderFields];
        NSString *cacheControl = [headers valueForKey:@"Cache-Control"];
        NSString *expires = [headers valueForKey:@"Expires"];
        // don't cache
        if (cacheControl == nil && expires == nil) {
            return nil;
        }
    }

    return cachedResponse;
}

  • 判斷request的cachePolicy是否==NSURLRequestUseProtocolCachePolicy
  • 取response的header,是否有cache-control和expire字段。
  • 存在cache-control,緩存
  • 存在expires,緩存
  • cache-control和expire都沒(méi)有,認(rèn)為不緩存。因?yàn)樘O(píng)果沒(méi)有提及到服務(wù)端沒(méi)有返回expire時(shí),默認(rèn)的緩存時(shí)間是多少,所以直接做不緩存處理。

Cache.db

可以用MesaSQlite打開(kāi)Cache.db,其中包括4張表,我們主要關(guān)注3個(gè)。

2.png

也可以直接在命令行中sqlite3 dbpath,打開(kāi)數(shù)據(jù)庫(kù)。

sqlite3 ~/Library/Developer/CoreSimulator/Devices/9C84830D-9B7B-454A-A245-B25E6318B765/data/Containers/Data/Application/B85B7BF4-CEDE-42E2-A6B2-F1BB5214DBE6/Library/Caches/com.summer.test/Cache.db 

查看表

sqlite> .tables
cfurl_cache_blob_data       cfurl_cache_response      
cfurl_cache_receiver_data   cfurl_cache_schema_version

1.cfurl_cache_blob_data

3.png

entry_ID是主鍵,request_object請(qǐng)求對(duì)象,response_object響應(yīng)對(duì)象,都是BLOB類型。在MeaseSqlite中查看時(shí),數(shù)據(jù)不能完全顯示出來(lái)。不知道有什么方法可以直接查看blob。
執(zhí)行了一條sql,看到response_object的內(nèi)容如下:

sqlite> SELECT response_object FROM cfurl_cache_blob_data;

bplist00?WVersionUArray?
"#?     __CFURLStringType\_CFURLString_Jhttp://static.m.yy.com/group1/M00/00/1D/dB95f1cZtpYAAAAAAAAFR2Vrq3A673.gif#A?????6?

只是可以大致知道包括了url,但其他的信息暫時(shí)不太清楚,如有知道的朋友,還請(qǐng)告知。

2.cfurl_cache_receiver_data

4.png

receiver_data存儲(chǔ)一些返回的數(shù)據(jù),如image,js,html,json等??梢宰孕胁榭?。

3.cfurl_cache_response

5.png

request_key:請(qǐng)求url
storage_policy:緩存策略

4.緩存的查找

  • 在cfurl_cache_response中根據(jù)request_key(即url)查到entry_ID
  • 在cfurl_cache_blob_data根據(jù)entry_ID找到response_object
  • 在cfurl_cache_receiver_data中根據(jù)entry_ID找到receiver_data

最后用response_object和receiver_data拼裝NSCachedURLResponse。

NSURLResponse *urlResponse = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[[request allHTTPHeaderFields] objectForKey:@"Accept"] expectedContentLength:[(NSData *)response_object length] textEncodingName:nil];

NSCachedURLResponse *cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:urlResponse data:receiver_data userInfo:nil storagePolicy:NSURLCacheStorageAllowed];

storagePolicy表明了object是否允許存儲(chǔ)。

typedef NS_ENUM(NSUInteger, NSURLCacheStoragePolicy)
{
    NSURLCacheStorageAllowed,   //內(nèi)存,磁盤(pán)都可以存
    NSURLCacheStorageAllowedInMemoryOnly,   //只能在內(nèi)存中
    NSURLCacheStorageNotAllowed, //不允許
};

刪除緩存

執(zhí)行完這句后,表中的數(shù)據(jù)全部清空了。

[[NSURLCache sharedURLCache] removeAllCachedResponses];

后語(yǔ)

本文簡(jiǎn)單的說(shuō)明了下緩存的位置,及表結(jié)構(gòu)。若各路大蝦有更加深入的理解,歡迎提出。

遺留問(wèn)題:
1. 如何方便查看blob數(shù)據(jù)
2. response_object到底是神馬?

2017.1.6更新--解決遺留問(wèn)題

1、如何方便查看blob數(shù)據(jù)
無(wú)意中看到一篇博文,也說(shuō)到對(duì)blob數(shù)據(jù)的查看,作者發(fā)現(xiàn)blob中導(dǎo)出的txt數(shù)據(jù),都有相似的地方,以xxx開(kāi)頭,然后去google解法。剎那間我也想起,我所疑惑的問(wèn)題,是不是可以有相同的處理。

于是乎,喵了眼txt,全都是以plist00開(kāi)頭。搜了一下,發(fā)現(xiàn)原來(lái)是plist的二進(jìn)制文件。并且有方法可以直接轉(zhuǎn)成plist。這刻,????深深的體會(huì)到,會(huì)google真能解決不少難題。

QQ20170106-0@2x.png
QQ20170106-1@2x.png

命令也很簡(jiǎn)單:

plutil -convert binary1 -o result.plist 1.txt

廬山真面目終于要來(lái)了~

QQ20170106-2@2x.png

2、關(guān)于response_object
response_object也是blob格式的數(shù)據(jù),我試著用同樣的方式打開(kāi),果然還是個(gè)plist。內(nèi)容如下,字段意思都比較明了。

QQ20170106-3@2x.png

參考:
Taking Advantage of iOS5 Built-In HTTP DiskCache
Caching and NSURLConnection
Binary Property Lists

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評(píng)論 19 139
  • Volley源碼分析之流程和緩存 前言 Android一開(kāi)始提供了HttpURLConnection和HttpCl...
    大寫(xiě)ls閱讀 745評(píng)論 0 6
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,097評(píng)論 0 9
  • 概覽 緩存組件應(yīng)該說(shuō)是每個(gè)客戶端程序必備的核心組件,試想對(duì)于每個(gè)界面的訪問(wèn)都必須重新請(qǐng)求勢(shì)必降低用戶體驗(yàn)。但是如何...
    默默_David閱讀 2,053評(píng)論 1 9
  • 上上周的新人培訓(xùn)已經(jīng)過(guò)去了,培訓(xùn)的時(shí)候我想了很多,進(jìn)入記者團(tuán)一年,從剛開(kāi)始什么都不懂到現(xiàn)在的初有涉獵,記者...
    潘潘潘tc閱讀 318評(píng)論 3 0

友情鏈接更多精彩內(nèi)容