一.背景介紹
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ō)明
二.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í)間笼踩。