系列文章:
前言
本文中拔疚,我們先介紹一下WKWebView,對比UIWebView它的優(yōu)缺點恤左。然后再看下WKWebView的主要API和其中的屬性贴唇,基本使用。
WkWebView的優(yōu)點和注意點
在2014年的WWDC上飞袋,蘋果針對WKWebView有專門的講解戳气。下邊,通過WWDC的課件上來看一下WKWebView的特點:
WKWebView的多進(jìn)程結(jié)構(gòu)
上圖中提到巧鸭,WKWebView的Multi-process Architecture
多進(jìn)程結(jié)構(gòu)具有【更完整的執(zhí)行流程控制】和【低能耗】的兩個特點瓶您。下邊,針對這兩個特點詳細(xì)解釋一下:
一般而言,一個程序開啟之后就會占用一個進(jìn)程呀袱,但是這不是唯一的芯肤。也存在一個程序?qū)?yīng)多個進(jìn)程(比如說程序的"多開"),或者一個進(jìn)程對應(yīng)多個程序的情況(比如說一個系統(tǒng)級別的工具DirectX压鉴,你同時打開多個游戲都會使用到它)崖咨。 對于WKWebView,你每創(chuàng)建一個webView出來油吭,默認(rèn)的都會對應(yīng)一個叫做Web Content Process
的進(jìn)程击蹲。當(dāng)然,你也可以不多對對
婉宰,可以多對一
歌豺。這樣就可以使創(chuàng)建出的多個webView對應(yīng)同一個的Web Content Process
的進(jìn)程。這個特點也涉及到了一個共享緩存數(shù)據(jù)的問題心包,后邊文章會詳細(xì)提到类咧。
基于這個特點,我們打開一個應(yīng)用程序A蟹腾,然后又在應(yīng)用A中打開一個webView痕惋,這個時候其實是兩個進(jìn)程,沒錯娃殖, WKWebView在APP進(jìn)程之外單獨開了一個進(jìn)程值戳, 這一點非常重要。如下圖:
因為WKWebView開辟的是獨立于App之外的進(jìn)程炉爆,webView占用的內(nèi)存是轉(zhuǎn)移到了自己的進(jìn)程中堕虹,而不是在App的進(jìn)程中。所以我們在查看內(nèi)存占用情況的時候會看到芬首,加載同一個網(wǎng)頁的時候(復(fù)雜繪制的大型網(wǎng)頁更明顯)赴捞,使用WKWebView的App會比使用UIWebView的App占用內(nèi)存小。 也許有同學(xué)會想到郁稍,這有什么用呢赦政,WKWebView不仍然還是在占用內(nèi)存。我們舉一個例子來說明這么設(shè)計的好處艺晴。當(dāng)開啟一個webView十分耗費內(nèi)存并且超過了蘋果的安全值時昼钻,使用UIWebView的App會被系統(tǒng)直接殺掉掸屡。而使用WKWebView的App封寞,被殺掉的只是WKWebView,體現(xiàn)在APP上的就是webView白屏了仅财。此時狈究,我們依然可以退出webView所在的界面,繼續(xù)愉快的玩耍App的其他功能盏求。
另外抖锥,關(guān)于占用內(nèi)存低
這個特點亿眠。我們監(jiān)測內(nèi)存的時候會發(fā)現(xiàn),除了剛開始打開webView的時候磅废,WKWebView會比UIWebView占用內(nèi)存低之外纳像。在后續(xù)的用戶操作中,WKWebView仍然會很好的內(nèi)存控制拯勉,而用了UIWebView的APP占用的內(nèi)存會呈現(xiàn)出上漲竟趾。我覺得,這也還是因為WKWebView多進(jìn)程架構(gòu)的功勞宫峦。如下圖:
WkWebView的注意點
在實際業(yè)務(wù)的接入和線上使用過程中导绷,WKWebView有些地方并不方便犀勒,比如Cookie
和黑魔法NSURLProtocol
。
Cookie: 在WKWebView中妥曲,并不能像UIWebView那樣很方便的設(shè)置Cookie贾费,雖然可以通過其它方式實現(xiàn),但是總體給人的感覺是Cookie并不在最開始蘋果設(shè)計WKWebView的規(guī)劃之內(nèi)檐盟。之所以這樣铸本,猜想是蘋果團隊在設(shè)計WKWebView的時候,就沒想過要讓客戶端干預(yù)Cookie遵堵,而是Cookie由HTML5后臺完全控制箱玷,這么做是為了保證敏感數(shù)據(jù)安全。所以在iOS11以下的版本API中陌宿,并沒有類似UIWebView中NSHTTPCookieStorage這樣的可以直接設(shè)置和存儲Cookie的官方類锡足。但是在各個App的實際開發(fā)過程中,給HTML5后臺傳入Cookie進(jìn)行身份校驗等屬于最最基本的操作壳坪,不可能按照蘋果的設(shè)想去進(jìn)行舶得。也正是因為不能方便設(shè)置Cookie的原因,在本文發(fā)布的時候爽蝴,很多大廠App的核心web業(yè)務(wù)并沒有使用WKWebView沐批,仍然是UIWebView。iOS11開始蝎亚,蘋果意識到了這個問題九孩,做了妥協(xié),新增WKHTTPCookieStorage來幫助開發(fā)者解決Cookie問題发框,雖然方便了躺彬,但是API仍然不穩(wěn)定,比如iOS11.3的時候就出現(xiàn)了一些變動。具體Cookie到底是什么宪拥,然后項目中解決Cookie的步驟仿野,我單獨寫了兩篇文章來詳細(xì)說明。《39- WKWebView項目實踐分享(四) - 先了解下Cookie》和《WKWebView項目實踐分享(五)- WKWebView如何加Cookie》
NSURLProtocol: 黑魔法在WKWebView是不被蘋果所允許的她君,網(wǎng)上有調(diào)用私有API來獲取和實現(xiàn)
NSURLProtocol
的方法脚作,雖然可以實現(xiàn)其部分功能,但是仍然有很多問題和風(fēng)險缔刹。我在后續(xù)接入WKWebView的過程中鳖枕,直接舍棄了NSURLProtocol
。下圖是
Cookie
和NSURLProtocol
在iOS11.3及其以前版本中存在的問題:
WKWebView中的`Cookie`和`NSURLProtocol`
其它需要注意的地方:
- 有的webView頁面出現(xiàn)偏移
- 需要自己處理AlertView彈框
- 需要自己處理a標(biāo)簽和target=_blank
- 頁面的重定向
- 跳轉(zhuǎn)到支付寶桨螺、打電話宾符、打開Appstore等需要自己處理openURL:
- OC調(diào)用JS的方法是異步的
- 修改User-Agent
- 跨域請求
- 白屏問題
當(dāng)然了,還有其它需要注意的地方灭翔,上邊只是在我的應(yīng)用中遇到的和解決的魏烫。關(guān)于其它大家可以自行網(wǎng)上搜索或者看我最下邊提供的參考文章的鏈接。
在下一篇文章里肝箱,我結(jié)合自己項目來說說基于當(dāng)前iOS11.3下是如何解決這些問題的哄褒。
WebKit介紹
UIWebView屬于UIKit框架,而WKWebView屬于獨立的WebKit框架煌张。這個框架中的所有API都和webView有關(guān)呐赡。從這里也可以看出,WKWebVie擁有的API是非常豐富的骏融,你能更加細(xì)致的把控webView的展示和交互過程链嘀。
另外,WKWebView的結(jié)構(gòu)和UIWebView的結(jié)構(gòu)不同档玻,如下:
WkWebView常用API概覽
下圖中怀泊,是WkWebView所涉及到的相關(guān)類及其作用:
下圖中,對上圖中的類按照功能作用進(jìn)行柜類误趴,可以分為如下幾種:
WkWebView簡單使用和說明
1. WKWebViewConfiguration和初始化
相較于UIWebView霹琼,WKWebView在初始化的時候可以傳入一個WKWebViewConfiguration
對象。這個WKWebViewConfiguration
的作用是對WKWebView進(jìn)行相關(guān)設(shè)置凉当,比如枣申,你可以設(shè)置否進(jìn)行在線自動播放、復(fù)制內(nèi)容的精確度看杭、給webView添加JS代碼等
忠藤。
以下幾行代碼,你就可以正常顯示一個webView泊窘,如下:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
// ...這里可以進(jìn)行設(shè)置 configuration.xxx = xxxx;
WKWebView *webView = [[WKWebView alloc] initWithFrame:myFrame configuration:configuration];
NSURL *URL = [NSURL URLWithString:@"https://www.baidu.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[webView loadRequest:request];
如果要進(jìn)行額外的設(shè)置熄驼,在WKWebViewConfiguration
中可能用到的一些類以及其作用,如下:
2. WKWebView的三大代理
使用代碼如下:
wkWebView.navigationDelegate = self; // WKNavigationDelegate
wkWwebView.UIDelegate = self; // WKUIDelegate
//...WKScriptMessageHandler的使用烘豹,在后續(xù)中文章專門講解
- WKNavigationDelegate
先說一下WKNavigationDelegate
瓜贾,它提供了WKWebView在整個加載過程中不同階段【比如開始加載、正在加載携悯、加載成功祭芦、加載失敗等】的回調(diào)方法°竟恚回調(diào)方法很多龟劲,可以讓我們掌控webView更多的加載細(xì)節(jié),然后對其加載過程進(jìn)行干預(yù)轴或。
下面兩圖中昌跌,我們可以看出WKWebView和UIWebView相比,新增加了哪些階段可以被開發(fā)者所操作:
下圖是在webView請求過程中蚕愤,WKNavigationDelegate提供的方法和UIWebView代理方法的區(qū)別:
另外,WKNavigationDelegate還有兩個重要的代理方法如下:
// 當(dāng)WKWebView對應(yīng)進(jìn)程退出時回調(diào)
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
// 當(dāng)一個正在提交的頁面在跳轉(zhuǎn)過程中出現(xiàn)錯誤時調(diào)用這個方法
- (void)webView:(WKWebView *)didFailNavigation:(WKNavigation *) withError:(NSError *)
-
WKUIDelegate
WKUIDelegate方法 WKScriptMessageHandler
3. 方法的參數(shù)解釋
上邊我們已經(jīng)介紹了WKWebViewConfiguration
的相關(guān)屬性饺蚊,在這里再介紹一下WKUIDelegate和WKNavigationDelegate中的其它的一些參數(shù)萍诱,以幫助我們更好理解WKWebView的設(shè)計意圖的使用它。
- WKFrameInfo
包含了一個網(wǎng)頁頁面的框架frame信息:
- mainFrame:是否是主窗口(框架)
- request:窗口(框架)的請求
- securityOrigin:框架的安全源
- webView:WkWebView
- 拓展:關(guān)于HTML中的frame
HTML中的frame
這里是從 W3CSchool得到的一些信息污呼,如果像更多的了解frame裕坊,可以查一下W3CSchool:
- <frameset> 標(biāo)簽:每個框架都可以設(shè)置不同的屬性,比如 border燕酷、scrolling籍凝、noresize 等等
- <frame> 標(biāo)簽:定義 frameset 中的一個特定的窗口(子窗口)(框架)
- 但是由于<frame> 標(biāo)簽對網(wǎng)頁可用性的負(fù)面影響,在 HTML 5 中 <frame> 標(biāo)簽沒有得到支持
通過WKFrameInfo苗缩,可以得到【當(dāng)前frame是不是當(dāng)前HTML頁面的主frame】等信息静浴。
- WKNavigationAction
WKNavigationAction類中包括的屬性
WKNavigationAction存在的方法之一是decidePolicyForNavigationAction:
,該方法是webView剛開始準(zhǔn)備向服務(wù)器發(fā)起請求的時候被調(diào)用挤渐。其中的幾個屬性的作用如下:
- 通過request我們可以得到發(fā)起的請求的信息苹享,包括HttpHeader、cookie浴麻、User Agent等得问。
- 通過navigationType我們可以來判斷進(jìn)入當(dāng)前回調(diào)方法的操作是返回上一頁,還是前進(jìn)到下一頁软免,還是重新刷新或者新加載一個URL等宫纬。
- 通過sourceFrame和targetFrame(destinationFrame)可以得到當(dāng)次請求來自的HTML頁面的frame的信息。
- WKNavigationResponse
WKNavigationResponse類中包括的屬性
WKNavigationResponse是在webView請求發(fā)送到服務(wù)器膏萧,然后服務(wù)器做出了響應(yīng)漓骚,App接收到響應(yīng)之后調(diào)用的方法decidePolicyForNavigationResponse:
中蝌衔。 通過其中的NSURLResponse可以得到請求回調(diào)的內(nèi)容。
Decision Handle(請求決策者)
下邊這兩個方法是發(fā)起請求前和收到請求后的回調(diào):-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler -(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
兩個方法中參數(shù)block
(void (^)(WKNavigationResponsePolicy))decisionHandler
的作用是是否繼續(xù)執(zhí)行后續(xù)請求流程蝌蹂。
在UIWebView中噩斟,判斷是否執(zhí)行當(dāng)前webView的請求是在shouldStartLoadWithRequest:
方法中,我們通過返回YES或者NO來決定孤个。 在WKWebView中剃允,在請求發(fā)起之前和接收到服務(wù)器返回的方法中都可以判斷當(dāng)前的webView是否是自己想要的,是否繼續(xù)執(zhí)行請求齐鲤。
- WKNavigationActionPolicyCancel 停止繼續(xù)請求
- WKNavigationActionPolicyAllow 繼續(xù)請求
- WKNavigationResponsePolicyCancel
- WKNavigationResponsePolicyAllow
- WKUserScript 我們在后續(xù)單獨的文章專門講解斥废。
參考
交流
希望能和大家交流技術(shù)
Blog:http://www.lilongcnc.cc
·