iOS-優(yōu)雅理解WKWebView

一.背景介紹

UIWebView自iOS2就有,iOS8出現(xiàn)了WKWebView蛤织,毫無(wú)疑問(wèn)WKWebView將逐步取代笨重的UIWebView。通過(guò)一些測(cè)試來(lái)看發(fā)現(xiàn)UIWebView占用過(guò)多內(nèi)存祖驱,且內(nèi)存峰值更是夸張舅柜。然而迟隅,新一代的WKWebView網(wǎng)頁(yè)加載速度也有進(jìn)一步的提升但骨。

下面我簡(jiǎn)單的羅列一些優(yōu)勢(shì):

  • 更多的支持HTML5的特性
  • 官方宣稱的高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢(shì)
  • Safari相同的JavaScript引擎
  • 將UIWebViewDelegate與UIWebView拆分成了14類與3個(gè)協(xié)議
  • 另外用的比較多的励七,增加加載進(jìn)度屬性:estimatedProgress

官方文檔說(shuō)明

Demo地址

二.UIWebView簡(jiǎn)單說(shuō)明

UIWebView使用不做詳細(xì)介紹,他的功能不僅可以加載HTML頁(yè)面奔缠,還支持pdf掠抬、word、txt校哎、各種圖片等等的顯示两波。其中代理協(xié)議使用UIWebViewDelegate,另外補(bǔ)充一點(diǎn)就是關(guān)于JS交互

  • js執(zhí)行OC代碼:

js是不能執(zhí)行oc代碼的闷哆,但是可以變相的執(zhí)行腰奋,js可以將要執(zhí)行的操作封裝到網(wǎng)絡(luò)請(qǐng)求里面,然后oc攔截這個(gè)請(qǐng)求抱怔,獲取url里面的字符串解析即可劣坊,這里用到代理協(xié)議的
<pre>

  • (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType函數(shù)。
    </pre>

  • oc調(diào)取寫好的js代碼

<pre>
// 實(shí)現(xiàn)自動(dòng)定位js代碼, htmlLocationID為定位的位置(由js開(kāi)發(fā)人員給出)屈留,實(shí)現(xiàn)自動(dòng)定位代碼局冰,應(yīng)該在網(wǎng)頁(yè)加載完成之后再調(diào)用
NSString *javascriptStr = [NSString stringWithFormat:@"window.location.href = '#%@'",htmlLocationID];
// webview執(zhí)行代碼
[self.webView stringByEvaluatingJavaScriptFromString:javascriptStr];
// 獲取網(wǎng)頁(yè)的title
NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"]
</pre>

三.WKWebView使用

基本使用

先導(dǎo)入:#import <WebKit/WebKit.h>

以下代碼展示了WKWebView簡(jiǎn)單顯示
<pre>
//1.創(chuàng)建webView
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
//2.創(chuàng)建請(qǐng)求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
//3.加載請(qǐng)求
[webView loadRequest:request];
//4. 視圖添加
[self.view addSubview:webView];
</pre>

實(shí)用函數(shù)

<pre>

  • (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));

  • (WKNavigation *)loadRequest:(NSURLRequest *)request;

  • (WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;

  • (WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL;
    </pre>

網(wǎng)頁(yè)導(dǎo)航刷新相關(guān)函數(shù)

和UIWebview幾乎一樣,不同的是有返回值灌危,WKNavigation(已更新)康二,另外增加了函數(shù)reloadFromOrigin和goToBackForwardListItem。

  • reloadFromOrigin會(huì)比較網(wǎng)絡(luò)數(shù)據(jù)是否有變化勇蝙,沒(méi)有變化則使用緩存沫勿,否則從新請(qǐng)求。
  • goToBackForwardListItem:比向前向后更強(qiáng)大浅蚪,可以跳轉(zhuǎn)到某個(gè)指定歷史頁(yè)面

<pre>
@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward;

  • (WKNavigation *)goBack;
  • (WKNavigation *)goForward;
  • (WKNavigation *)reload;
  • (WKNavigation *)reloadFromOrigin; // 增加的函數(shù)
  • (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; // 增加的函數(shù)
  • (void)stopLoading;
    </pre>

相關(guān)類介紹

<pre>
WKBackForwardList: 之前訪問(wèn)過(guò)的 web 頁(yè)面的列表藕帜,可以通過(guò)后退和前進(jìn)動(dòng)作來(lái)訪問(wèn)到。
WKBackForwardListItem: webview 中后退列表里的某一個(gè)網(wǎng)頁(yè)惜傲。
WKFrameInfo: 包含一個(gè)網(wǎng)頁(yè)的布局信息洽故。
WKNavigation: 包含一個(gè)網(wǎng)頁(yè)的加載進(jìn)度信息。
WKNavigationAction: 包含可能讓網(wǎng)頁(yè)導(dǎo)航變化的信息盗誊,用于判斷是否做出導(dǎo)航變化时甚。
WKNavigationResponse: 包含可能讓網(wǎng)頁(yè)導(dǎo)航變化的返回內(nèi)容信息,用于判斷是否做出導(dǎo)航變化哈踱。
WKPreferences: 概括一個(gè) webview 的偏好設(shè)置荒适。
WKProcessPool: 表示一個(gè) web 內(nèi)容加載池。
WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法开镣。
WKScriptMessage: 包含網(wǎng)頁(yè)發(fā)出的信息刀诬。
WKUserScript: 表示可以被網(wǎng)頁(yè)接受的用戶腳本。
WKWebViewConfiguration: 初始化 webview 的設(shè)置邪财。
WKWindowFeatures: 指定加載新網(wǎng)頁(yè)時(shí)的窗口屬性陕壹。

WKWebsiteDataStore:website站點(diǎn)使用各種數(shù)據(jù)類型质欲,比如:cookies, disk and memory caches, and persistent data such as WebSQL,IndexedDB databases, and local storage

WKWebViewConfiguration:webview初始化配置
</pre>

代理協(xié)議

  • WKNavigationDelegate

該代理提供的方法,可以用來(lái)追蹤加載過(guò)程(頁(yè)面開(kāi)始加載糠馆、加載完成嘶伟、加載失敗)又碌、決定是否執(zhí)行跳轉(zhuǎn)九昧。

<pre>
// 2.頁(yè)面開(kāi)始加載時(shí)調(diào)用

  • (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
    //3. 當(dāng)內(nèi)容開(kāi)始返回時(shí)調(diào)用
  • (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
    // 4.頁(yè)面加載完成之后調(diào)用
  • (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
    // 頁(yè)面加載失敗時(shí)調(diào)用
  • (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
    </pre>

頁(yè)面跳轉(zhuǎn)的代理方法有三種,分為(收到跳轉(zhuǎn)與決定是否跳轉(zhuǎn)兩種)

<pre>
// 接收到服務(wù)器跳轉(zhuǎn)請(qǐng)求之后調(diào)用

  • (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
    // 3.在收到響應(yīng)后毕匀,決定是否跳轉(zhuǎn)
  • (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
    // 1.在發(fā)送請(qǐng)求之前铸鹰,決定是否跳轉(zhuǎn)
  • (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
    </pre>

<strong>數(shù)字表示了正確加載時(shí)的調(diào)用順序</strong>

  • WKUIDelegate

UI界面相關(guān),原生控件支持期揪,三種提示框:輸入掉奄、確認(rèn)、警告凤薛。首先將web提示框攔截然后再做處理姓建。

<pre>
/// 創(chuàng)建一個(gè)新的WebView

  • (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
    /// 輸入框

  • (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
    /// 確認(rèn)框

  • (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
    /// 警告框

  • (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
    </pre>

  • WKScriptMessageHandler
    這個(gè)協(xié)議中包含一個(gè)必須實(shí)現(xiàn)的方法,這個(gè)方法是提高App與web端交互的關(guān)鍵缤苫,它可以直接將接收到的JS腳本轉(zhuǎn)為OC或Swift對(duì)象速兔。

<pre>
/// message: 收到的腳本信息.

  • (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
    </pre>

注意事項(xiàng)

  • 1.線程不安全
    來(lái)源于蘋果文檔
    <pre>
    Concurrency Note
    The WebKit framework is not thread-safe. If you call functions or methods in this framework, you must do so exclusively on the main program thread.
    </pre>

WKWebView應(yīng)用

1. 修改docunment

<pre>
WKUserContentController *wkuserCVC = [[WKUserContentController alloc]init];
WKUserScript *script = [[WKUserScript alloc]initWithSource:@"js code" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
[wkuserCVC addUserScript:script];
</pre>

2.監(jiān)聽(tīng)web內(nèi)容加載進(jìn)度、是否加載完成

WKWebView 有一個(gè)屬性estimatedProgress,這個(gè)就是加載進(jìn)度活玲。我們利用KVO監(jiān)聽(tīng)這個(gè)屬性值的變化涣狗,就可以顯示加載進(jìn)度了。
<pre>
[self.webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
</pre>

3. 跨域問(wèn)題

跨域問(wèn)題可以采用手動(dòng)跳轉(zhuǎn)的方式

<pre>

  • (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    //這里攔截判斷
    }

</pre>

補(bǔ)充:HTML5 性能數(shù)據(jù)了解

  • 白屏?xí)r間

白屏?xí)r間無(wú)論安卓還是iOS在加載網(wǎng)頁(yè)的時(shí)候都會(huì)存在的問(wèn)題舒憾,也是目前無(wú)法解決的镀钓;

  • 頁(yè)面耗時(shí)

頁(yè)面耗時(shí)指的是開(kāi)始加載這個(gè)網(wǎng)頁(yè)到整個(gè)頁(yè)面load完成即渲染完成的時(shí)間;

  • 加載鏈接的一些性能數(shù)據(jù)

重定向時(shí)間镀迂,DNS解析時(shí)間丁溅,TCP鏈接時(shí)間,request請(qǐng)求時(shí)間探遵,response響應(yīng)時(shí)間窟赏,dom節(jié)點(diǎn)解析時(shí)間,page渲染時(shí)間箱季,同時(shí)我們還需要抓取資源時(shí)序數(shù)據(jù)涯穷,

什么是資源時(shí)序數(shù)據(jù)呢?

每個(gè)網(wǎng)頁(yè)是有很多個(gè)資源組成的藏雏,有.js拷况、.png、.css、.script等等赚瘦,我們就需要將這些每個(gè)資源鏈接的耗時(shí)拿到最疆,是什么類型的資源,完整鏈接蚤告;對(duì)于客戶來(lái)說(shuō)有了這些還不夠,還需要JS錯(cuò)誤服爷,頁(yè)面的ajax請(qǐng)求杜恰。JS錯(cuò)誤獲取的當(dāng)然是堆棧信息和錯(cuò)誤類型。ajax請(qǐng)求一般是獲取三個(gè)時(shí)間仍源,響應(yīng)時(shí)間心褐,ajax下載時(shí)間,ajax回調(diào)時(shí)間笼踩。

Demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逗爹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嚎于,更是在濱河造成了極大的恐慌掘而,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件于购,死亡現(xiàn)場(chǎng)離奇詭異袍睡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)肋僧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門斑胜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嫌吠,你說(shuō)我怎么就攤上這事止潘。” “怎么了辫诅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵凭戴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我泥栖,道長(zhǎng)簇宽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任吧享,我火速辦了婚禮魏割,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钢颂。我一直安慰自己钞它,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著遭垛,像睡著了一般尼桶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锯仪,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天泵督,我揣著相機(jī)與錄音,去河邊找鬼庶喜。 笑死小腊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的久窟。 我是一名探鬼主播秩冈,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斥扛!你這毒婦竟也來(lái)了入问?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤稀颁,失蹤者是張志新(化名)和其女友劉穎芬失,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峻村,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡麸折,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粘昨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垢啼。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖张肾,靈堂內(nèi)的尸體忽然破棺而出芭析,到底是詐尸還是另有隱情,我是刑警寧澤吞瞪,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布馁启,位于F島的核電站,受9級(jí)特大地震影響芍秆,放射性物質(zhì)發(fā)生泄漏惯疙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一妖啥、第九天 我趴在偏房一處隱蔽的房頂上張望霉颠。 院中可真熱鬧,春花似錦荆虱、人聲如沸蒿偎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诉位。三九已至骑脱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苍糠,已是汗流浹背叁丧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岳瞭,地道東北人歹袁。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像寝优,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子枫耳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言 關(guān)于UIWebView的介紹乏矾,相信看過(guò)上文的小伙伴們,已經(jīng)大概清楚了吧迁杨,如果有問(wèn)題钻心,歡迎提問(wèn)。 本文是本系列...
    CoderLF閱讀 8,974評(píng)論 2 12
  • 前言 關(guān)于UIWebView的介紹痒给,相信看過(guò)上文的小伙伴們,已經(jīng)大概清楚了吧骏全,如果有問(wèn)題苍柏,歡迎提問(wèn)。 本文是本系列...
    Dark_Angel閱讀 28,914評(píng)論 67 291
  • 通過(guò)學(xué)習(xí)姜贡,你將會(huì)學(xué)習(xí)以下幾個(gè)方面的內(nèi)容: **什么是WKWebView以及它和UIWebView的區(qū)別是什么 **...
    SOI閱讀 11,645評(píng)論 18 42
  • http://www.cnblogs.com/mddblog/p/5281748.html 一试吁、整體介紹 UIWe...
    F麥子閱讀 1,236評(píng)論 0 2
  • 【手寫愛(ài)情繪本3.0】要在時(shí)間的荒野,沒(méi)有早一步也沒(méi)有晚一步楼咳,于千萬(wàn)人之中去邂逅自己的愛(ài)人熄捍,那是太難得的緣份。更多...
    主播亞?wèn)|閱讀 534評(píng)論 4 4