轉(zhuǎn)- WKWebView從入門(mén)到趟坑

轉(zhuǎn)載自: http://www.itdecent.cn/p/90a90bd13aac

WKWebView從入門(mén)到趟坑

開(kāi)發(fā)App的過(guò)程中,常常會(huì)遇到在A(yíng)pp內(nèi)部加載網(wǎng)頁(yè),通常用UIWebView加載。而這個(gè)自iOS2.0開(kāi)始使用的Web容器一直是開(kāi)發(fā)的心?。杭虞d速度慢,占用內(nèi)存多,優(yōu)化困難。如果加載網(wǎng)頁(yè)多,還可能因?yàn)檫^(guò)量占用內(nèi)存而給系統(tǒng)kill掉。各種優(yōu)化的方法效果也不那么明顯,常見(jiàn)的優(yōu)化緩存方式:

1、盡量使用 GET 請(qǐng)求,iOS 系統(tǒng) SDK 會(huì)自動(dòng)幫你做緩存。你需要的僅僅是設(shè)置下內(nèi)存緩存大小、磁盤(pán)緩存大小、以及緩存路徑。只要設(shè)置了這兩行代碼,基本就可滿(mǎn)足80%的緩存需求。

設(shè)置緩存.jpg

2、Web資源離線(xiàn)加載,熱更新資源,完成另外20%的緩存需求(Hybrid框架的Web部分)。

可是無(wú)數(shù)開(kāi)發(fā)者嘗試自己做一個(gè)“簡(jiǎn)陋而脆弱的”系統(tǒng)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)緩存的功能,效果往往是事倍功半 。

初識(shí) WKWebView

UIWebView從 iOS2 就有,iOS8 以后,蘋(píng)果推出了新框架 WebKit,提供了替換 UIWebView 的組件 WKWebView。各種 UIWebView 的性能問(wèn)題沒(méi)有了,速度更快了,占用內(nèi)存少了,體驗(yàn)更好了,下面列舉一些其它的優(yōu)勢(shì):

1、在性能、穩(wěn)定性、功能方面有很大提升(加載速度,內(nèi)存的提升誰(shuí)用誰(shuí)知道)

2、更多的支持 HTML5 的特性

3、官方宣稱(chēng)的高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢(shì)

4、Safari 相同的 JavaScript 引擎

5、將 UIWebViewDelegate 與 UIWebView 拆分成了14類(lèi)與3個(gè)協(xié)議,包含該更細(xì)節(jié)功能的實(shí)現(xiàn)。

相比之下,WKWebView 復(fù)雜得多,一些常用API如下:

容器相關(guān)

WKWebView.jpg

JavaScript 配置相關(guān)

JavaScript API.jpg

存儲(chǔ)相關(guān)(只支持iOS9以上)

存儲(chǔ)類(lèi)型.jpg

存儲(chǔ) API.jpg

頁(yè)面加載相關(guān)

WKWebView loadRequest.jpg

代理相關(guān)

WKNavigationDelegate.jpg

看完API以后,要掌握 WKWebView 并不難,難的是如何處理iOS版本碎片化兼容問(wèn)題。

性能對(duì)比測(cè)試

都說(shuō)提高多么多么大的性能,實(shí)測(cè)告訴你 WKWebView 的性能有多好,下面用實(shí)際項(xiàng)目做個(gè)對(duì)比測(cè)試:

UIWebView 首次加載 www.58.com 首頁(yè),耗時(shí) 0.0154584ms,內(nèi)存消耗 24.1 MB

UIWebView耗時(shí).jpg

UIWebView內(nèi)存消耗.jpg

WKWebView 首次加載 www.58.com 首頁(yè),耗時(shí) 0.013875ms,內(nèi)存消耗僅 6.4 MB

WKWebView耗時(shí).jpg

WKWebView內(nèi)存消耗.jpg

結(jié)論:加載耗時(shí)差別不大,WKWebView 的內(nèi)存優(yōu)化減少了幾乎4倍,更重要的是,無(wú)論 WKWebView 跳轉(zhuǎn)多少 Web 頁(yè)面都沒(méi)有內(nèi)存泄漏了。WKWebView 使用和 Safari 相同的 Nitro JS 引擎性能,對(duì)HTML5性能也提升了4倍。

WKWebView 之坑

新技術(shù)的出現(xiàn)必然會(huì)或多或少的瑕疵,WKWebView 也不例外。

1、關(guān)于緩存

在 WKWebsiteDataStore 出現(xiàn)之前(iOS 9 中),WKWebView 是沒(méi)有緩存,也無(wú)從清理。WKWebView 是基于 WebKit 框架的,它會(huì)忽視先前使用的網(wǎng)絡(luò)存儲(chǔ) NSURLCache, NSHTTPCookieStorage, NSCredentialStorage等,它也有自己的存儲(chǔ)空間用來(lái)存儲(chǔ)cookie和cache,其他的網(wǎng)絡(luò)類(lèi)如NSURLConnection 是無(wú)法訪(fǎng)問(wèn)到的。 同時(shí)WKWebView發(fā)起的資源請(qǐng)求也是不經(jīng)過(guò)NSURLProtocol的,導(dǎo)致無(wú)法攔截或自定義新請(qǐng)求。

體驗(yàn)過(guò) WKWebView 的一定會(huì)遇到修改了H5頁(yè)面,APP打開(kāi)時(shí)卻沒(méi)有即時(shí)更新的問(wèn)題(實(shí)在是緩存得太好了),iOS 8的時(shí)候只能增加時(shí)間戳的方式解決這個(gè)問(wèn)題(調(diào)試下使用,生產(chǎn)環(huán)境就只能要求前端修改Cache-Controll了),如下:

時(shí)間戳更新.jpg

iOS 9以后終于可以使用 WKWebsiteDataStore 來(lái)清理緩存。后來(lái)Google一下,又發(fā)現(xiàn)iOS 8可以通過(guò)清理 Library 目錄下的 Cookies 目錄來(lái)清除緩存,于是

清除WKWebView緩存.jpg

緩存清理的坑趟過(guò)了,喜大普奔。

2、關(guān)于 Cookie

在使用 UIWebVIew 的時(shí)候我們并不關(guān)注 Cookie,因?yàn)樵谡{(diào)用登錄接口的時(shí)候無(wú)論是AFNetworking,還是其他,登錄成功之后都會(huì)自動(dòng)保存在

[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies 中,以后再使用也會(huì)自動(dòng)去獲?。ㄟ@里有個(gè) UIWebView 的坑:訪(fǎng)問(wèn)的鏈接越多,如不處理Cookie,它會(huì)加載越來(lái)越多的無(wú)效 Cookie 導(dǎo)致內(nèi)容急劇增大)。但 WKWebView 的存儲(chǔ)體系與 UIWebVIew 完全不一樣,只能手動(dòng)給它添加 Cookie,如下:

WKWebView設(shè)置cookie.jpg

但即便如此,Cookie 還是會(huì)偶現(xiàn)丟失的問(wèn)題,最終只好采用每次 Web 開(kāi)始加載之時(shí)判斷 Cookie 是否存在,否則手動(dòng)添加重新加載,如下:

WKWebView設(shè)置cookie.jpg

Cookie 獲取的坑趟過(guò)了,再次喜大普奔。

3、關(guān)于跨域

WebKit框架對(duì)跨域進(jìn)行了安全性檢查限制,不允許跨域,比如從一個(gè) HTTP 頁(yè)對(duì) HTTPS 發(fā)起請(qǐng)求是無(wú)效的(有一個(gè)界面要跳到支付寶頁(yè)面去支付,死活沒(méi)反應(yīng))。而系統(tǒng)的 Safari ,iOS 10出現(xiàn)的 SFSafariViewController 都是支持跨域的,因此解決辦法如下:

跨域跳轉(zhuǎn).jpg

對(duì)于自身域名,還是建議全站 HTTPS 化吧(大勢(shì)所趨)。

4、關(guān)于 JavaScript 交互

UIWebView 使用的 JavaScriptCore 框架,交互時(shí)為 JavaScript 運(yùn)行的上下文環(huán)境 JSContext 注入對(duì)象 Bridge;WKWebView 使用的 WebKit 框架,交互時(shí)為 webkit.messageHandlers 注入對(duì)象,如下:

JavaScript注入.jpg

前端H5需要做判斷兩種不同注入方式帶來(lái)的不同調(diào)用方式:

js調(diào)用.jpg

5、關(guān)于 NSURLProtocol 攔截

WKWebView 基于 WebKit 框架,與 UIWebView 機(jī)制不同:加載過(guò)程中所有的請(qǐng)求都不經(jīng)過(guò) NSURLProtocol,換句話(huà)說(shuō)就是 WKWebView 無(wú)法攔截響應(yīng)數(shù)據(jù) 鑒于之前大部分 Hybrid 框架的離線(xiàn)預(yù)加載機(jī)制都依賴(lài)于攔截功能,這意味著廢掉很多程序猿們辛辛苦苦設(shè)計(jì)實(shí)現(xiàn)的 Hybrid 框架(內(nèi)功盡失,感覺(jué)身體被掏空),再加上 WKWebView 自身的坑不少,因此很多團(tuán)隊(duì)都不會(huì)輕易替換掉 UIWebView。擁抱變化吧,WKWebView 遲早會(huì)取代 UIWebView 成為最佳 Web 容器(iOS 9帶來(lái)的 SFSafariViewController 更是武功全廢,啥都干不了,只能干瞪眼)。

那么問(wèn)題來(lái)了,如何設(shè)計(jì)新的 Hybrid 框架呢?此處出門(mén)左轉(zhuǎn),點(diǎn)擊文章開(kāi)頭進(jìn)入公眾號(hào)歷史文章,查看《通用Web&Native交互協(xié)議設(shè)計(jì)方案》。

6、關(guān)于 POST 請(qǐng)求

簡(jiǎn)書(shū)http://www.itdecent.cn/p/403853b63537中有關(guān)于這個(gè)坑的具體描述,筆者這里就不再做研究,這里只說(shuō)明怎么趟過(guò)的坑:使用通用的 Web&Native 交互協(xié)議,為 Web 提供 Native POST 請(qǐng)求的接口+回調(diào) CallBack 即可,參見(jiàn)關(guān)于 JavaScript 交互。

7、關(guān)于本地 HTML 加載

當(dāng)使用 loadRequest 來(lái)讀取本地 Documents 目錄的 HTML 文件時(shí),WKWebView 是無(wú)法讀取成功的,只能通iOS 9的新接口加載

load loacl html.jpg

但是在iOS9以下的版本是沒(méi)提供這個(gè)便利的方法的,解決辦法:先將本地 HTML 文件的數(shù)據(jù) copy 到 tmp 目錄中,然后再使用 loadRequest 來(lái)加載。但是如果在 HTML 中加入了其他資源文件,例如 js,css,image 等也必須一同 copy 到 tmp 中,這個(gè)是非常蛋疼的事情了。然而還有更蛋疼的事:iOS 8下還必須 copy 到 tmp 的 www 目錄下 WKWebView 才能讀取(Word天,心中千萬(wàn)只草泥馬狂奔而過(guò))。參見(jiàn)http://stackoverflow.com/questions/24882834/wkwebview-not-loading-local-files-under-ios-8

8、關(guān)于捏合手勢(shì)

很多人都喜歡使用 UIWebView 的捏合手勢(shì)來(lái)進(jìn)行放大和縮小,觀(guān)看 Web 內(nèi)容,但 WKWebView 在手機(jī)上不支持,卻支持其他iOS設(shè)備(草泥馬再次狂奔而過(guò))。

不支持捏合手勢(shì).png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • UIWebView 之痛 開(kāi)發(fā)App的過(guò)程中,常常會(huì)遇到在A(yíng)pp內(nèi)部加載網(wǎng)頁(yè),通常用UIWebView加載。而這個(gè)...
    zyl04401閱讀 16,226評(píng)論 46 157
  • UIWebView 之痛 開(kāi)發(fā)App的過(guò)程中,常常會(huì)遇到在A(yíng)pp內(nèi)部加載網(wǎng)頁(yè),通常用UIWebView加載。而這個(gè)...
    Style_mao閱讀 1,481評(píng)論 1 5
  • 前言 關(guān)于UIWebView的介紹,相信看過(guò)上文的小伙伴們,已經(jīng)大概清楚了吧,如果有問(wèn)題,歡迎提問(wèn)。 本文是本系列...
    CoderLF閱讀 9,345評(píng)論 2 12
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,334評(píng)論 4 61
  • 成功的老師往往會(huì)對(duì)開(kāi)學(xué)第一天的教學(xué)有著很好的規(guī)劃。普通教師在開(kāi)學(xué)第一天往往直切正題,只顧講課或者做個(gè)小游戲來(lái)拉近學(xué)...
    不一樣的精彩1216閱讀 561評(píng)論 0 0

友情鏈接更多精彩內(nèi)容