Objective-c下具有下載功能的NSURLCache類CustomURLCache,customurlcache
最近在做iOS APP開發的過程中遇到了這麼一個問題:我開發的是一個閱讀類的App,本文介面是通過UIWebViewController來實現的,現在要實現文章離線閱讀功能。即將當前web頁面所有的資源請求結果都下載都本地。在網上找了很多方法,發現都不是很好。後來還是決定從cache入手:iOS內建的NSURLCache並不支援將cache下載到自訂的目錄底下,所以只有複寫NSURLCache這個類來實現這些功能。在網上找到一個他人寫的CustomURLCache的類,但是發現使用的過程中程式會崩,於是一步一步調試代碼,定位到該類的錯誤,對代碼進行了修改,修複了這個bug。而隨著iOS8的推出,發現設定自訂的URLCache必須要在AppDelegate.m的 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 函數中使用才行,否則無效。無奈,只好進一步對代碼進行修改。終於可以適配ios8了。今天將這部分代碼分享出來,希望對大家有用。代碼我已經託管到github上,大家可以自行下載。
同時為了相容系統NSURLCache的功能,CustomURLCache有兩種模式,NORMAL_MODE和DOWNLOAD_MODE,NORMALMODE下的CustomCache和NSURLCache的功能是一樣的;而DOWNLOADMODE下的CustomURLCache則可以實現包含自訂下載目錄,設定到期時間的子功能的下載功能。
接下來用例子教大家如何使用CustomURLCache這個類。假設我們在做一個閱讀類的App,本文頁面用UIWebViewController來展示。現在需要實現一個離線下載的功能,即將當前網頁的所有訪問到的資源(html檔案,圖片,JavaScript,CSS等等)全部都儲存到本地。用CustomURLCache就可以很容易地實現這個功能。
在AppDelegate.m中將CustomURLCache設定為全域URLCache
上文已經講到了,在iOS8中,設定全域URLCache必須在AppDelegate.m中的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions實現,所以第一步就是將我們CustomURLCache在該函數中設定為全域URLCache:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ ...... //Init custom cache CustomURLCache *_mCache = [[CustomURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024 diskCapacity:200 * 1024 * 1024 diskPath:nil cacheTime:0 subDirectory:nil]; [NSURLCache setSharedURLCache:_mCache]; return YES;}
這段代碼將我們的CustomURLCache設定為了全域的URLCache,其中的參數有如下意義:
- diskCapacity:就是使用者佈建的這個cache的大小
- diskPath:cache的下載路徑,如果設定為nil的話,那麼該類將會自動將當前應用的緩衝目錄作為下載路徑
- cacheTime:cache的到期時間,如果設定為0的話,那麼cache將永遠不會到期
- subDirectory:這是位於diskPath下的子目錄,意為當前的cache會存在哪個子目錄中。不過在初始化的時候只用將其設定為nil即可
值得說明的時候,在初始化之後其實沒有任何變化,因為這個時候的預設模式是NORMAL_MODE,即跟NSURLCache是一樣的。所以感覺不出什麼不一樣。不要著急,很快我們就需要使用到DOWNLOAD_MODE了。
將CustomURLCache設定為DOWNLOAD_MODE
好了,假設我們在第一個頁面選中了一篇文章,然後點擊計入了本文頁面,本文頁面的布局很簡單,就是一個UIWebView,我們需要用其顯示一個網頁,並且將所有需要請求的資源都下載到本地自訂的目錄中。這個時候就需要用到DOWNLOAD_MODE了。實現很簡單,在本文介面的UIViewController的- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil或者init函數中將CustomURLCache設定為DOWNLOAD_MODE:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { ...... _mCache = (CustomURLCache *)[NSURLCache sharedURLCache]; [_mCache changeToDownloadMode:_subDir]; [NSURLCache setSharedURLCache:_mCache]; } return self;}
現在我們就成功地將CustomURLCache設定為了下載模式,在執行[_mCache changeToDownloadMode:_subDir];時需要指定下載子目錄,就位於diskPath下的下載子目錄。接下來所有的web請求資源都會下載到我們的自訂目錄了。
將CustomURLCache恢複到NORMAL_MODE
好了,現在web頁面也展現出來了,所有的web請求資源都下載到本地了,該退出了。回退到第一個頁面,並且不再需要DOWNLOAD_MODE,我們要將其恢複為NORMAL_MODE,那麼在當前UIViewController下的dealloc函數或者其他使用者自訂的退出函數中加入如下代碼(在這裡我使用的是自己的退出函數):
- (void)backToMainpage:(id)sender { if (不再需要文章緩衝) { NSLog(@"刪除文章緩衝"); [_mCache removeCustomRequestDictionary ]; } else { //do nothing } //不再使用自訂緩衝,而是換到系統的緩衝 [_mCache changeToNormalMode]; [self.navigationController popViewControllerAnimated:YES];}
好了,如果你沒有刪除文章緩衝,那麼當我們再次就如本文頁面的時候,你會發現頁面很快就加在完成了。原因很簡單,當你再次進入該UIViewController的時候,程式又會執行[_mCache changeToDownloadMode:_subDir];這時,CustomURLCache在接到URL請求的時候會先到_subDir路徑下去找是否有緩衝的資源,如果找到了,並且還不到期,那麼就會自動加在本地的資源,如果沒有找到或者到期了,那麼會重新通過網路請求。所以你知道為什麼這麼快就完成了,因為所有的資源都是在本地的!
好了,簡單地使用就介紹到這裡了。希望對大家有協助。同時,如果大家喜歡的話就請在GitHub上fork或者star以下吧,萬分感謝!