1. NSURLCache簡介:
iOS對NSURLRequest提供了7種快取策略:(實際上能用的只有4種)
NSURLRequestUseProtocolCachePolicy // 預設的快取策略(取決於協議)
NSURLRequestReloadIgnoringLocalCacheData // 忽略快取,重新請求
NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略快取,重新請求
NSURLRequestReturnCacheDataElseLoad// 有快取就用快取,沒有快取就重新請求
NSURLRequestReturnCacheDataDontLoad// 有快取就用快取,沒有快取就不發請求,當做請求出錯處理(用於離線模式)
NSURLRequestReloadRevalidatingCacheData // 未實現
NSURLCache的常見用法
(1)獲得全域性快取物件(沒必要手動建立)NSURLCache *cache = [NSURLCache sharedURLCache];
(2)設定記憶體快取的最大容量(位元組為單位,預設為512KB)- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;
(3)設定硬碟快取的最大容量(位元組為單位,預設為10M)- (void)setDiskCapacity:(NSUInteger)diskCapacity;
(4)硬碟快取的位置:沙盒/Library/Caches
(5)取得某個請求的快取- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request;
(6)清除某個請求的快取- (void)removeCachedResponseForRequest:(NSURLRequest *)request;
(7)清除所有的快取- (void)removeAllCachedResponses;
快取GET請求
要想對某個GET請求進行資料快取,非常簡單
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 設定快取策略
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
只要設定了快取策略,系統會自動利用NSURLCache進行資料快取
快取的注意事項
快取的設定需要根據具體的情況考慮,如果請求某個URL的返回資料:
(1)經常更新:不能用快取!比如股票、彩票資料
(2)一成不變:果斷用快取
(3)偶爾更新:可以定期更改快取策略 或者 清除快取
提示:如果大量使用快取,會越積越大,建議定期清除快取
2.藉助ETag或Last-Modified判斷檔案快取是否有效
通過列印一個response例項,可以看到response header部分如下所示:
我們可以在請求資料時先上傳Etag或者是Last-Modified讓伺服器端進行判斷,若資料未發生變動則載入本地資料,否則載入伺服器端資料。
請求的HeaderValue和響應的HeaderValue如下所示:
下面以Etag為例進行資料快取:
先設定快取記憶體和硬碟大小:
NSURLCache *urlCache= [[NSURLCache alloc]initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil]; [NSURLCache setSharedURLCache:urlCache];
下載一張圖片:
- (IBAction)download:(UIButton *)sender { NSURL *url=[NSURL URLWithString:@"http://192.168.1.102:8080/love/images/bg2.jpg"]; NSMutableURLRequest *mRequest=[NSMutableURLRequest requestWithURL:url]; mRequest.cachePolicy=NSURLRequestReloadIgnoringCacheData; mRequest.timeoutInterval=5; // 根據請求獲取到`被快取的響應`! NSCachedURLResponse *cacheResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:mRequest]; //cacheResponse不存在時設定etag為空 if (!cacheResponse) { self.etag=nil; } //傳送etag if (self.etag.length>0) { //NSLog(@"Etag=%@",self.etag); [mRequest setValue:self.etag forHTTPHeaderField:@"If-None-Match"]; } [NSURLConnection sendAsynchronousRequest:mRequest queue:[NSOperationQueue new] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { // 型別轉換(如果將父類設定給子類,需要強制轉換) NSHTTPURLResponse *httpResponse=(NSHTTPURLResponse*)response; // NSLog(@"res=%@",httpResponse); // 判斷響應的狀態碼是否是 304 Not Modified (更多狀態碼含義解釋: https://github.com/ChenYilong/iOSDevelopmentTips) if (httpResponse.statusCode==304) { NSLog(@"載入本地快取圖片"); // 如果是,使用本地快取 // 根據請求獲取到`被快取的響應`! NSCachedURLResponse *cacheResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:mRequest]; // 拿到快取的資料 data = cacheResponse.data; }else{ NSLog(@"請求網路端圖片"); } if(data){ [self performSelectorOnMainThread:@selector(setImage:) withObject:data waitUntilDone:YES]; } self.etag=httpResponse.allHeaderFields[@"Etag"]; }]; // NSArray *arr=NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES); // NSString *path=[arr objectAtIndex:0]; // NSLog(@"%@",path); } -(void)setImage:(NSData*)data{ // NSLog(@"setimage"); self.imageView.image=[UIImage imageWithData:data]; }
清除所有快取:
- (IBAction)clearCache:(UIButton *)sender {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
參考文獻: