iOS 網路請求緩衝:NSURLCache詳解

來源:互聯網
上載者:User

標籤:

我讀過一些開源項目的網路請求緩衝的代碼,基本上都是採用在本地存檔案的方式進行緩衝。如果你打算在你的項目中加入網路請求的緩衝,可能你並不需要自己造一個輪子,了解一下 NSURLCache 就足夠。本文為大家接收的就是ios開發中的NSURLCache相關使用,一起來看看吧。

緩衝

首先, NSURLCache 提供的是記憶體以及磁碟的綜合緩衝機制。許多文章談到,使用NSURLCache 之前需要在 AppDelegate 中緩衝空間的設定:

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

NSURLCache *URLCache = [[NSURLCachealloc] initWithMemoryCapacity:4 * 1024 * 1024

diskCapacity:20 * 1024 * 1024

diskPath:nil];

[NSURLCachesetSharedURLCache:URLCache];

}

然而如果你不添加上面的代碼,並且運行如下代碼,可以看到:

print(NSURLCache.sharedURLCache().diskCapacity)//output://10000000

print(NSURLCache.sharedURLCache().memoryCapacity)//output://512000

也就是說,其實預設就已經設定好了512kb的記憶體緩衝空間,以及10MB的磁碟緩衝空間。可能你的代碼中並沒有寫任何與 NSURLCache 有關的東西,但其實它已經默默的開始幫你進行緩衝了。

已經緩衝上了,但是怎麼使用緩衝呢?請繼續往下。

緩衝策略

GET

不用多說, NSURLCache 只會對你的 GET 請求進行緩衝。

NSURLRequestCachePolicy

NSURLRequest 中有個屬性:

public var cachePolicy: NSURLRequestCachePolicy { get }

你可以通過這個屬性來佈建要求的緩衝策略,

public enum NSURLRequestCachePolicy : UInt {

case UseProtocolCachePolicy // 預設值

case ReloadIgnoringLocalCacheData // 不使用快取資料

case ReloadIgnoringLocalAndRemoteCacheData // Unimplemented

public static var ReloadIgnoringCacheData: NSURLRequestCachePolicy { get }

case ReturnCacheDataElseLoad // 無論緩衝是否到期都是用緩衝,沒有緩衝就進行網路請求

case ReturnCacheDataDontLoad // 無論緩衝是否到期都是用緩衝,沒有緩衝也不會進行網路請求

case ReloadRevalidatingCacheData // Unimplemented

}

其實其他幾個值都比較好理解,唯獨預設值 UseProtocolCachePolicy 讓我不太懂。

字面上的意思是 按照協議的緩衝策略進行緩衝 ,那麼這是什麼協議呢? http協議

詳細:RFC 2616, Section 13

伺服器返回的回應標頭中會有這樣的欄位: Cache-Control: max-age or Cache-Control: s- maxage ,通過 Cache-Control 來指定緩衝策略, max-age 來表示到期時間。根據這些欄位緩衝機制再採用如下策略:

· 如果本地沒有快取資料,則進行網路請求。

· 如果本地有緩衝,並且緩衝沒有失效,則使用緩衝。

· 如果緩衝已經失效,則詢問伺服器資料是否改變,如果沒改變,依然使用緩衝,如果改變了則請求新資料。

· 如果沒有指定是否失效,那麼系統將自己判斷緩衝是否失效。(通常認為是6-24小時的有效時間)

其實我以前對 Cache-Control 之類的也並不太瞭解 T_T,自己默默的print了一下回應標頭,你可以看到:

print((responseas? NSHTTPURLResponse)?.allHeaderFields)

//回應標頭中:Cache-Control: no-cache

這也就是為什麼,雖然 NSURLCache 一直在默默的緩衝,但是我並沒有感受到,當然或許你那裡不一樣。這個 no-cache 就表示不緩衝。

這裡要額外提一句,看到網上有同學說自己出現了某個請求資料一直使用緩衝,沒有被更新。這種情況可能就是伺服器返回的 Cache-Control 有誤。

開啟沙箱路徑下的Library/Caches 中,你可以看到快取檔案:


這可以說明存在磁碟上的資料是存在資料庫裡的,效能不用擔心。開啟資料庫檔案就可以看到請求的資料。


在 cfurl_cache_response 表中可以看到有一個欄位是 request_key ,通過裡面的值可以推斷每一個 response 是通過請求的 url+參數 來作為 key 儲存的。

當然,經過我的多次實驗,在 Cache-Control: no-cache 的情況下, NSURLCache也會進行緩衝,但是並不使用快取資料。

總結一下:預設情況下 NSURLCache 的緩衝策略是根據http協議來的,伺服器通過 Cache-Control: max-age 欄位來告訴 NSURLCache 是否需要快取資料。

緩衝封裝

如果你不打算採用http協議的緩衝策略,依然可以使用 NSURLCache 進行緩衝。

public funccachedResponseForRequest(request: NSURLRequest) -> NSCachedURLResponse?

你可以通過這個方法,傳入請求,來擷取緩衝。 NSCachedURLResponse 儲存了上次請求的資料以及回應標頭。

public funcstoreCachedResponse(cachedResponse: NSCachedURLResponse, forRequestrequest: NSURLRequest)

NSURLSessionDelegate 協議中有如下方法,可以對即將緩衝的資料進行修改,添加userInfo,在代理方法中必須調用completionHandler,傳入將要緩衝的資料,如果傳nil則表示不緩衝。

optionalpublic funcURLSession(session: NSURLSession,

dataTask: NSURLSessionDataTask,

willCacheResponseproposedResponse: NSCachedURLResponse,

completionHandler: (NSCachedURLResponse?) -> Void)

Alamofire 中可以這樣寫:

Alamofire.Manager

.sharedInstance

.delegate

.dataTaskWillCacheResponse = { (session, task, cachedResponse) -> NSCachedURLResponse? in

var userInfo = [NSObject : AnyObject]()

// 設定userInfo

return NSCachedURLResponse(response: cachedResponse.response,

data: cachedResponse.data,

userInfo: userInfo,

storagePolicy: cachedResponse.storagePolicy)

}

 

來源:伯樂線上



 iOS 網路請求緩衝:NSURLCache詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.