今天電面時被問到了UIWebView的本地緩存,以前未關注過webview的緩存,因此查了下博文html
原文連接:http://blog.csdn.net/zhuqilin0/article/details/6653532web
在手機應用程序開發中,爲了減小與服務端的交互次數,加快用戶的響應速度,通常都會在iOS設備中加一個緩存的機制,前面一篇文章介紹了iOS設備的內存緩存,這篇文章將設計一個本地緩存的機制。緩存
功能需求session
這個緩存機制知足下面這些功能。併發
一、能夠將數據緩存到本地磁盤。測試
二、能夠判斷一個資源是否已經被緩存。若是已經被緩存,在請求相同的資源,先到本地磁盤搜索。網站
三、能夠判斷文件緩存何時過時。這裏爲了簡單起見這裏,咱們在請求url資源的時候,給每次請求的文件設定一個過時的時間。ui
四、能夠實現:若是文件已經被緩存,並且沒有過時,這將本地的數據返回,不然從新請求url。atom
五、能夠實現:若是文件下載不成功或者下載沒有完成,下次打開程序的時候,移除這些沒有成功或者沒有下載完成的文件。url
六、能夠實現:同時請求或者下載多個資源。
設計實現:
一、設計一個CacheItem類,用來請求一個web鏈接,它的一個實例表示一個緩存項。這個CacheItem類,須要一個url建立一個NSURLConnection,去請求web資源。使用CacheItem類主要用來請求web資源。
二、在NSURLConnection開始請求以前,調用CachedDownloadManager類,來搜索和管理本地的緩存文件。將緩存文件的狀況保存到一個字典類中。這個字典設計以下:
上面這個字典裏面嵌套了字典。裏面那層字典表示一個緩存項的緩存信息:下載結束時間、下載開始時間、緩存有效時間、緩存過時時間、緩存到本地的路徑。
下面看下CachedDownloadManager類。用它來實現和封裝咱們的緩存策略。
從上面代碼能夠看出,這個管理緩存的類中,有一個緩存字典:cacheDictionary,用來表示全部資源的緩存狀況;cacheDictionaryPath用來表示緩存的路徑;saveCacheDictionary用來將緩存字典歸檔到本地文件中。download:urlMustExpireInSeconds:updateExpiryDateIfInCache是一個公共接口,經過傳遞url、緩存過時時間、是否更新緩存過時時間三個參數來方便的使用,實現咱們的緩存策略。
三、若是這個文件已經被下載,並且沒有過時,則從本地獲取文件的數據。若是文件已通過期,則從新下載。咱們經過download:urlMustExpireInSeconds:updateExpiryDateIfInCache方法來實現,主要看這個方法的代碼:
四、下面咱們設計緩存項下載成功和失敗的兩個委託方法:
當咱們下載成功的時候,修改緩存字典中的下載時間,表示已經下載完成,並且須要將請求的資源數據緩存到本地:
這樣就基本上完成了咱們須要的功能,下面看看咱們如何使用咱們設計的緩存功能。
例子場景:
咱們用一個UIWebView來顯示stackoverflow這個網站,咱們在這個網站的內容緩存到本地20秒,若是在20秒內用戶去請求該網站,則從本地文件中獲取內容,不然過了20秒,則從新獲取數據,並緩存到本地。
在界面上拖放一個button和一個webview控件,以下圖。
這樣咱們能夠很方便使用前面定義好的類。咱們在viewDidLoad 中實例化一個CachedDownloadManager,並設置它的委託爲self。當下載完成的時候,執行CachedDownloadManager的下載成功的委託方法。
- (void)viewDidLoad { [super viewDidLoad]; [self setTitle:@"本地緩存測試"]; CachedDownloadManager *newManager = [[CachedDownloadManager alloc] init]; self.downloadManager = newManager; [newManager release]; [self.downloadManager setDelegate:self]; }
在button的點擊事件中加入下面代碼,請求stackoverflow :
static NSString *url = @"http://stackoverflow.com"; [self.downloadManager download:url urlMustExpireInSeconds:20.0f updateExpiryDateIfInCache:YES];
上面的代碼表示將這個stackoverflow的緩存事件設置爲20s,而且若是在20s內有相同的請求,則從本地獲取stackoverflow的內容數據。updateExpiryDateIfInCache設置爲yes表示:在此請求的時候,緩存時間又更新爲20s,相似咱們的session。若是設置成no,則第一次請求20s以後,該緩存就過時。
請求完成以後會執行CachedDownloadManager的委託方法。咱們將數據展現在uiwebview中,代碼以下:
- (void) cachedDownloadManagerSucceeded:(CachedDownloadManager *)paramSender remoteURL:(NSURL *)paramRemoteURL localURL:(NSURL *)paramLocalURL aboutToBeReleasedData:(NSData *)paramAboutToBeReleasedData isCachedData:(BOOL)paramIsCachedData{ [webview loadData:paramAboutToBeReleasedData MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:[NSURL URLWithString:@"http://stackoverflow.com"]]; }
這樣咱們就實現了20s的緩存。
效果:
第一次點擊測試按鈕:
20s內點擊按鈕,程序就從本地獲取數據,比較快速的就顯示出該網頁了。
總結:
本文經過代碼和實例設計了一個iPhone應用程序本地緩存的方案。固然這個方案不是最好的,若是你有更好的思路,歡迎告訴我。