iOS網絡——NSURLCache設置網絡請求緩存

今天在看HTTP協議,看到了response頭中的cache-control,因而就深刻的研究了一下。發現了iOS中一個一直被我忽略的類——NSURLCache類。php

 

NSURLCachehtml

NSURLCache用於緩存網絡請求,也就是NSURLRequest,而後根據咱們設置的NSURLCache策略進行相應的緩存。web

首先介紹一下各類策略sql

策略 意義

UseProtocolCachePolicy數據庫

 默認行爲
 ReloadIgnoringLocalCacheData  不使用緩存
 ReloadIgnoringLocalAndRemoteCacheData*  我是認真地,不使用任何緩存
 ReturnCacheDataElseLoad  使用緩存(無論它是否過時),若是緩存中沒有,那從網絡加載吧
 ReturnCacheDataDontLoad  離線模式:使用緩存(無論它是否過時),可是從網絡加載
 ReloadRevalidatingCacheData* 在使用前去服務器驗證 

其中ReloadIgnoringLocalAndRemoteCacheData和ReloadRevalidatingCacheData兩種是沒有實現的,能夠不看。緩存

在建立對request使用cache的時候會讓咱們選擇以上的某種策略進行,也就是服務器

+ (instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;

該方法讓咱們設置策略和時間,而後request會根據策略和時間來進行相應的調度。網絡

 

感覺NSURLCache工具

這裏使用默認的緩存策略ReturnCacheDataElseLoad緩存策略,spa

首先須要建立NSURLCache類

NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];

1.這裏能夠看到,建立參數咱們制定了 4 * 1024 * 1024的內存(4MB) ,沒有使用磁盤空間。

2.NSURLCache使用[NSURLCache sharedURLCache]建立默認的的緩存行爲,默認爲 4(MB) 內存和 20(MB)磁盤空間,這裏咱們使用自定義的,因此要setSharedCache。

而後建立request和connection進行請求

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];

實現NSURLConnectionDelegate協議

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"finish");
}

而後運行開一下請求,這裏用的工具是Charles

能夠看到只有一次請求,再看控制檯輸出

2015-08-04 09:29:55.297 requestCache[19405:6375355] finish
2015-08-04 09:29:55.301 requestCache[19405:6375355] finish
2015-08-04 09:29:55.310 requestCache[19405:6375355] finish
2015-08-04 09:29:55.451 requestCache[19405:6375355] finish
2015-08-04 09:29:55.618 requestCache[19405:6375355] finish
2015-08-04 09:29:55.784 requestCache[19405:6375355] finish
2015-08-04 09:29:55.984 requestCache[19405:6375355] finish
2015-08-04 09:29:56.120 requestCache[19405:6375355] finish

因此說屢次的請求只會進行一次請求,由於在內存中NSURLCache爲咱們緩存了一份response,一旦有一樣請求就會使用緩存。

 

緩存持久化

緩存若是設定本地磁盤就會爲咱們自動進行持久化,修改NSURLCache建立代碼

    NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
    [NSURLCache setSharedURLCache:URLCache];

設置了20MB的本地磁盤,而後運行程序,進行請求發現仍是請求一次沒有變化。可是在次運行程序進行請求就會發現,一次遠程請求也不會進行了!

打開沙盒,發如今 Library/Caches/bundleId+項目名/下面有三個文件

這不就是sqlite麼!原來NSURLCache幫咱們用sqlite將請求存入了數據庫,而後當有相同請求時就會調用緩存!

能夠想到webView若是加載一個靜態頁面不用只用請求一次,而且在效果要更新的時候遠程請求會有多爽!

 

默認策略

默認策略是 UseProtocolCachePolicy 從字面上來看是說,使用協議緩存策略,可是什麼是協議緩存策略呢?

在HTTP協議的response頭中,有一個字段是cache-control,由服務器來告訴客戶端如何使用緩存。

下面是一個response頭

 

能夠看到cache-control指定的行爲是public,max-age=5

這裏先介紹一下各類指令

對應上表,能夠看出了剛纔響應頭是要求緩存全部內容,緩存5秒失效,5秒後還要請求遠程服務器。

對應PHP就是header("Cache-Control:public,max-age=5");

 

僞造響應

若是咱們想讓一些請求,有特定的響應,咱們能夠本身來製做響應

    NSLog(@"%@",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]);
    
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:3];
    NSURLCache * cache = [NSURLCache sharedURLCache];
    
    NSData *contentData = [@"123" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] MIMEType:@"text/html" expectedContentLength:1000 textEncodingName:@"UTF-8"];
    NSCachedURLResponse *cacheRespone = [[NSCachedURLResponse alloc] initWithResponse:response data:contentData];
    
    [cache storeCachedResponse:cacheRespone forRequest:request];
    
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];

如上代碼,建立了一個針對@"http://172.16.25.44/test1.php"請求的響應,而且讓 cache 對該響應進行了存儲。

實現

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",dataString);
}

輸出結果以下

2015-08-04 09:48:58.825 requestCache[19503:6441561] 123
2015-08-04 09:48:58.826 requestCache[19503:6441561] finish
2015-08-04 09:48:58.983 requestCache[19503:6441561] 123
2015-08-04 09:48:58.984 requestCache[19503:6441561] finish
2015-08-04 09:48:59.167 requestCache[19503:6441561] 123
2015-08-04 09:48:59.167 requestCache[19503:6441561] finish
2015-08-04 09:48:59.334 requestCache[19503:6441561] 123
2015-08-04 09:48:59.335 requestCache[19503:6441561] finish

能夠看到輸出的是咱們自定義的123,而不是服務器返回的1。

 

修改響應內容

修改響應內容須要咱們實現NSURLConnectionDataDelegate 協議並實現

-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    NSMutableData *mutableData = [[cachedResponse data] mutableCopy];
    
    //添加數據
    
    NSCachedURLResponse *response = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:mutableData];
    return response;
}

應爲 NSCachedURLResponse 的屬性都是readonly的,因此咱們想要添加內容就要建立一個可變副本增減內容。

相關文章
相關標籤/搜索