iosuiwebview清除緩存
① iOS webView利用NSURLProtocol實現離線緩存
最近公司有一個需求,要對webView(UIWebView)實現緩存機制。即在無網條件下,打開webView頁面,能讀取到網頁,有網情況下,緩存未過期也可以使用本地緩存,加快用戶讀取網頁速度。
實現緩存策略的方案有很多,為了保證有效,可控等多方面因素,本文採用NSURLProtocol來實現該需求,它的優勢很多,樓主就不再累述了。
關於NSURLProtocol,網上給出了很多資料,但很多方案都有缺陷,包括github上有star的項目,會遇到在特定情況下,網頁載入不出來的問題,導致一直顯示空白頁。本文成功解決了這些問題,目前該項目已在線上穩定運行。
寫這篇文章,一方面為了自己,做一些整理,另一方面如果小夥伴,遇到類似需求後,不至於走太多彎路,所謂前人栽樹,後人乘涼。廢話不多說了,直接上內容。
首先關於URL Loading System
簡單來說, URL Loading System 是iOS一系列網路請求類的集合,包括老的NSConnection和現在流行的NSURLSession,還包括一些請求認證的類,一個sessionConfig的類,還有關於處理請求緩存的類等,當然也包括NSURLProtocol類。
當我們需要攔截URL請求時,我們只要通過 - registerClass: 方法注冊我們的NSURLProtocol類,然後去重寫NSURLProtocol類中的方法,就能對我們發起的請求做處理。
NSURLProtocol 是一個抽象類,所以使用的時候必須定義一個它的子類:
需要攔截URL的控制器中注冊該類:
記得在不需要的時候,及時關閉它:
注意一點:如果是基於 NSURLSession 進行的請求,注冊的時候需要注冊到 NSURLSessionConfiguration 中:
注冊成功之後,需要子類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
取消流程
流程圖:
② iOS-關於WebView在長時間使用下的卡頓現象測試
我的手機里常駐瀏覽器是海豚,最近在使用的時候發現出現卡頓現象,讓使用體驗變得非常不爽,大過年的閑來無聊就做了點測試。
症狀:當一個WebView在重復打開達數十次甚至上百次時整個頁面在滑動時會出現非常明顯的卡頓現象。
解決方法:將WebView銷毀,重新創建一個即可消除卡頓,除此之外刷新WebView亦或是其他方法都無法消除卡頓。
為了了解其實際情況,我製作了一個簡單的Demo,通過Xcode相關工具實際檢驗來確定卡頓緣由。
我簡單地創建了一個對照組,分別是UIWebView以及WKWebView製作的簡易瀏覽器。
最開始我的想法是大量載入界面造成的卡頓可能是Safari內核的問題,UIWebView及WKWebView在大量重復載入後可能都會出現卡頓現象,總不可能海豚瀏覽器還是在使用UIWebViewd吧哈哈哈……哈哈……哈……
在實驗結束後我開始不確定是我的檢驗手法出現問題還是海豚V9.3.0版本是使用UIWebView搭建的,本來我惡意地猜測是Safari內核有問題或者在WebView內部做了某些限制,在WebView大量重復使用後會限制什麼東西,結果沒想到最大的可能居然只是UIWebView的問題,真是索然無味。
兩個對照組使用同樣的樣本進行測試,測試設備為iPhone5S,版本為9.3.2,測試樣本為一本網路小說的前200章。
初始狀態:
以上兩張分別是UIWebView在初始狀態下默認載入小說首頁時靜止狀態與滑動狀態下的資源利用率,可以發現CPU佔用不高,此時界面也屬於流暢狀態。
以上兩張分別是WKWebView的靜止狀態及滑動狀態的資源佔有率,不得不說蘋果對WKKit的優化做足了心,內存佔有根本不是一個級別的。
我們在WK的滑動圖可以看出,此時兩者在滑動狀態下的CPU使用率是相近的,而實際上兩者在初始狀態下滑動手感也並無差別。
五十章節後:
可以看到,UIWebView的內存佔用減少了,這是因為進入章節界面後圖片的減少,之後的數據中內存佔用大多保持在這一程度左右。而CPU在滑動狀態下的佔用率則是大大提升,並且峰值可以達到40%左右。
而相對的,WKWebView的佔用率並沒有明顯提升。
此時,UIWebView的網頁已經可以感覺到少許的卡頓。
一百章節後:
UIWebView的界面已造成明顯卡頓現象,同時,CPU的佔用率在滑動狀態下也達到50%以上(測試下峰值曾達到80%以上)
WK淡定地表示再來一百章。
兩百章後:
UIWebView因為瘋狂卡頓導致Demo 頁面長時間凝滯,無法測試。
而此時WK依舊淡定。
結論:Just Fuck UIWebView.出現的卡頓現象只是UIWebView自身缺陷導致的CPU使用量暴增從而造成的卡頓,在不清楚蘋果在當初設計UIWebView的時候做了什麼而在WKKit中又修改了什麼東西彌補了這部分缺陷的情況下這只是又一次老生常談,告訴大家拋棄UIWebView投向WKKit的懷抱。
③ wkwebview的緩存設置策略
對於iOS8之後新推出的WKWebView還是有顯著的有點相對於傳統的UIWebView; 但是對於一些網頁的緩存策略就比較蒼白了,盡管UIWebView已經有很有的緩存設置策略了,但是對於剛推出的WKWbeView並沒有設置緩存的功能;
UIWebView設置緩存的方法:
不過自iOS9之後WKWebView緩存設置的API才正式推出:
types是指存在指定緩存類型的一個集合,包括:
④ 解決UIWebView內存佔用過高
iOS8以上使用WKWebView。。需要支持iOS7,這就必須要UIWebview和WKWebview的混合使用,這里講一下怎麼解決UIWebView內存問題
首先你在APPDelagate,改變緩存策略,使他到達你設定的值後,進行強制內存回收,這樣做還有一個好處就是提高網頁載入速度
然後在頁面消失的時候,強制把webview的delegate設置為nil,並清除緩存
⑤ ios webview的cookie怎麼清楚
UIWebView清除Cookie:
//清除cookies
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
[storage deleteCookie:cookie];
}
UIWebView清除緩存:
//清除UIWebView的緩存
[[NSURLCachesharedURLCache] removeAllCachedResponses];
NSURLCache * cache = [NSURLCache sharedURLCache];
[cache removeAllCachedResponses];
[cache setDiskCapacity:0];
[cache setMemoryCapacity:0];
⑥ ios前端有緩存
ios前端有緩存的解決方法:
1.此時在ios app的沙盒文件中將保存好已經緩存的文件,如果此時沒有退出APP,那麼緩存的內容同時也會保存在內存中;如下圖(此處針對的UIWebView)
2.此時可以看到這Caches文件中,後面的Paul.H5下面多了Cache.db的資料庫,打開資料庫可以看到以下內容;注意 此時的圖片資源也是保存在Paul.H5下面的文件中
⑦ UIWebView怎麼設置緩存
UIWebView可以看一下sdk,之前做過的瀏覽器都是用哈希表來緩存的。
⑧ 請問清除UIWebView的緩存
設置程序清空
⑨ 如何解決 UIWebview 內存泄漏
解決的第一個步驟就是無縫切換到wkwebview:
我動手封裝了一下,識別了一下iOS的版本,IOS8+的就切換到wkwebview。
沒想到這么一切換,出了問題。(切換wkwebview的注意點)「AController中的wkwebview」 和 「BController中的wkwebview」的localstorage信息不一致。
什麼意思呢,就是在B中保存了數據,回到A中,數據沒同步到。
貌似真的無解.....
只能一個個API查看(怎麼查看?)
後來發現一個東西有點可疑wkwebviewconfiguration。(configuration)
其中有一個值,processPool,描述是:The process pool from which to obtain the view』s Web Content process.
再搜了一下,stackoverflow上有關於的cookie的問答剛好和這個有關,處理方法是將config中的processPool變為單例。
然後我也弄成單例,然後問題就解決了。
然後IOS7怎麼辦?
解決的第二個步驟是檢查是否存在循環引用。
哈哈,我也是切換過去才知道原來內存泄漏是有解的。
最初也是試了一輪網上的方案,然後都沒什麼用。
就在我盡人事聽天命的時候,我在controller退出的時候,手動置空了所有引用。在頁面返回的時候強制清了一輪緩存
[plain] view plain
NSUserDefaults.standardUserDefaults().setInteger(0, forKey: "WebKitCacheModelPreferenceKey")
NSUserDefaults.standardUserDefaults().synchronize()
然後再去看內存,還是會增長,不過已經平和了很多,頁面返回內存也會降低回去。