我讀過一些開源項目的網絡請求緩存的代碼,基本上都是採用在本地存文件的方式進行緩存。若是你打算在你的項目中加入網絡請求的緩存,可能你並不須要本身造一個輪子,瞭解一下NSURLCache
就足夠。html
這是一個Apple已經爲你準備好了的網絡請求緩存類。網上對這個類的介紹並很少,而且有的文章講得很不詳細。但願這篇文章能讓你對NSURLCache
有一個比較詳細的瞭解。git
首先,NSURLCache
提供的是內存以及磁盤的綜合緩存機制。許多文章談到,使用NSURLCache
以前須要在AppDelegate
中緩存空間的設置:github
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
diskCapacity:20 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
}複製代碼
然而若是你不添加上面的代碼,而且運行以下代碼,能夠看到:數據庫
print(NSURLCache.sharedURLCache().diskCapacity)
//output:
//10000000
print(NSURLCache.sharedURLCache().memoryCapacity)
//output:
//512000複製代碼
也就是說,其實默認就已經設置好了512kb的內存緩存空間,以及10MB的磁盤緩存空間。可能你的代碼中並無寫任何與NSURLCache
有關的東西,但其實它已經默默的開始幫你進行緩存了。swift
已經緩存上了,可是怎麼使用緩存呢?請繼續往下。緩存
不用多說,NSURLCache
只會對你的GET
請求進行緩存。服務器
NSURLRequest
中有個屬性:網絡
public var cachePolicy: NSURLRequestCachePolicy { get }複製代碼
你能夠經過這個屬性來設置請求的緩存策略,session
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
讓我不太懂。app
字面上的意思是按照協議的緩存策略進行緩存,那麼這是什麼協議呢?http協議。
服務器返回的響應頭中會有這樣的字段:Cache-Control: max-age
or Cache-Control: s- maxage
,經過Cache-Control
來指定緩存策略,max-age
來表示過時時間。根據這些字段緩存機制再採用以下策略:
其實我之前對Cache-Control
之類的也並不太瞭解 T_T,本身默默的print了一下響應頭,你能夠看到:
print((response as? NSHTTPURLResponse)?.allHeaderFields)
//響應頭中:Cache-Control: no-cache複製代碼
這也就是爲何,雖然NSURLCache
一直在默默的緩存,可是我並無感覺到,固然或許你那裏不同。這個(勘誤) 修正:no-cache表示不使用緩存,可是會緩存,no-store表示是不進行緩存。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 func cachedResponseForRequest(request: NSURLRequest) -> NSCachedURLResponse?複製代碼
你能夠經過這個方法,傳入請求,來獲取緩存。NSCachedURLResponse
保存了上次請求的數據以及響應頭。
public func storeCachedResponse(cachedResponse: NSCachedURLResponse, forRequest request: NSURLRequest)複製代碼
NSURLSessionDelegate
協議中有以下方法,能夠對即將緩存的數據進行修改,添加userInfo,在代理方法中必須調用completionHandler,傳入將要緩存的數據,若是傳nil則表示不緩存。
optional public func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, willCacheResponse proposedResponse: 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)
}複製代碼
#參考
我也只是簡單的對NSURLCache
進行了介紹,須要深刻了解的話你們仍是須要拜讀一下文章,但願能給你們一些幫助: