iOS webView利用NSURLProtocol實現離線緩存

前言

????????最近公司有一個需求,要對webView(UIWebView)實現緩存機制。即在無網條件下,打開webView頁面,能讀取到網頁,有網情況下,緩存未過期也可以使用本地緩存,加快用戶讀取網頁速度。

????????實現緩存策略的方案有很多,為了保證有效,可控等多方面因素,本文采用NSURLProtocol來實現該需求,它的優勢很多,樓主就不再累述了。

? ? ? ? 關于NSURLProtocol,網上給出了很多資料,但很多方案都有缺陷,包括github上有star的項目,會遇到在特定情況下,網頁加載不出來的問題,導致一直顯示空白頁。本文成功解決了這些問題,目前該項目已在線上穩定運行。

? ? ? ? 寫這篇文章,一方面為了自己,做一些整理,另一方面如果小伙伴,遇到類似需求后,不至于走太多彎路,所謂前人栽樹,后人乘涼。廢話不多說了,直接上內容。

首先關于URL Loading System

簡單來說,URL Loading System是iOS一系列網絡請求類的集合,包括老的NSConnection和現在流行的NSURLSession,還包括一些請求認證的類,一個sessionConfig的類,還有關于處理請求緩存的類等,當然也包括NSURLProtocol類。

NSURLProtocol

當我們需要攔截URL請求時,我們只要通過?- registerClass:?方法注冊我們的NSURLProtocol類,然后去重寫NSURLProtocol類中的方法,就能對我們發起的請求做處理。


具體使用方法:

1. 繼承于NSURLProtocol

NSURLProtocol 是一個抽象類,所以使用的時候必須定義一個它的子類:

2. 注冊

需要攔截URL的控制器中注冊該類:

記得在不需要的時候,及時關閉它:

注意一點:如果是基于 NSURLSession 進行的請求,注冊的時候需要注冊到 NSURLSessionConfiguration 中:

3.子類必須實現的方法

注冊成功之后,需要子類CLURLSessionProtocol去實現抽象方法:


+ (BOOL)canInitWithRequest:(NSURLRequest*)request

此處可以攔截需要處理的URL,已經處理過的請求,需要標記請求是否被處理過,防止死循環

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request

這個方法用來統一處理請求 request 對象的,可以修改頭信息,或者重定向。沒有特殊需要,則直接return request;

如果要在這里做重定向以及頭信息的時候注意檢查是否已經添加,因為這個方法可能被調用多次,也可以在后面的方法中做。

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)a toRequest:(NSURLRequest*)b

判斷網絡請求是否一致,一致的話使用緩存數據。沒需要就調用 super 的方法。

- (void)startLoading

這個方法作用很大,把當前請求的request攔截下來以后,在這個方法里面對這個request做各種處理,比如添加請求頭,重定向網絡,使用自定義的緩存等。

重點:需要標記已經處理過的 request:

- (void)stopLoading

取消流程

4.整理下業務需求:

流程圖:

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容