蘋(píng)果在iOS8中推出了webkit新框架,提供了WKWebview組件用來(lái)替換存在各種問(wèn)題的UIWebview,用WKWebview加載網(wǎng)頁(yè),相較于UIWebview速度更快了,內(nèi)存占用更少了。WKWebview還提供了更加豐富的接口,功能更加強(qiáng)大,真是喜大普奔的好事兒,下面就讓我們看看如何使用WKWebView吧!
WKWebView的優(yōu)勢(shì):
1)WKWebview在性能、穩(wěn)定性上和UIwebview相比
2)WKWebView更多的支持HTML5的特性
3)WKWebView更快,占用內(nèi)存可能只有UIWebView的1/3 ~ 1/4
4)WKWebView高達(dá)60fps的滾動(dòng)刷新率和豐富的內(nèi)置手勢(shì)(Built-in gestures)
5)WKWebView具有Safari相同的JavaScript引擎Nitro(JJT四個(gè)進(jìn)程解釋執(zhí)行優(yōu)化js代碼)(Fast JavaScript)
6)WKWebView增加了加載進(jìn)度屬性
7)app和網(wǎng)頁(yè)的交互更簡(jiǎn)便(Easy app-webpage communication)
8)響應(yīng)滾動(dòng)(Responsive scrolling)
9)更省電量 (battery)
1.加載網(wǎng)頁(yè)
func setUpWKwebView() {
let webConfiguration = WKWebViewConfiguration()
let myURL = URL(string: "https://weibo.com")
webView = WKWebView(frame: view.bounds, configuration: webConfiguration)
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
view.addSubview(webView)
}
2.WKWebView的代理方法
WKWebView提供了WKNavigationDelegate和WKUIDelegate兩個(gè)代理協(xié)議
-
WKNavigationDelegate
提供了可用來(lái)追蹤加載過(guò)程的代理方法
//頁(yè)面開(kāi)始加載時(shí)調(diào)用
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!);
//當(dāng)內(nèi)容開(kāi)始返回時(shí)調(diào)用
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!);
// 頁(yè)面加載完成之后調(diào)用
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!);
//頁(yè)面加載失敗時(shí)調(diào)用
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error);
也提供了可用來(lái)監(jiān)聽(tīng)頁(yè)面跳轉(zhuǎn)的代理方法,分為:收到跳轉(zhuǎn)與決定是否跳轉(zhuǎn)兩種
// 接收到服務(wù)器跳轉(zhuǎn)請(qǐng)求之后調(diào)用
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!);
// 在收到響應(yīng)后,決定是否跳轉(zhuǎn)
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) ;
// 在發(fā)送請(qǐng)求之前,決定是否跳轉(zhuǎn)
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) ;
-
WKUIDelegate
WKWebView創(chuàng)建初始化加載的一些配置
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?
與界面彈出提示框相關(guān)的代理方法,針對(duì)于web界面的三種提示框(警告框、確認(rèn)框、輸入框)分別對(duì)應(yīng)三種代理方法。
//處理網(wǎng)頁(yè)js中的提示框,若不使用該方法,則提示框無(wú)效
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void)
//處理網(wǎng)頁(yè)js中的確認(rèn)框,若不使用該方法,則確認(rèn)框無(wú)效
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void)
//處理網(wǎng)頁(yè)js中的文本輸入
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void)
iOS9.0中新加入的,處理WKWebView關(guān)閉的時(shí)間
func webViewDidClose(_ webView: WKWebView)
在 iOS 10 中新加入的用于自定義Peek and Pop的代理方法
func webView(_ webView: WKWebView, shouldPreviewElement elementInfo: WKPreviewElementInfo) -> Bool;
func webView(_ webView: WKWebView, previewingViewControllerForElement elementInfo: WKPreviewElementInfo, defaultActions previewActions: [WKPreviewActionItem]) -> UIViewController?
func webView(_ webView: WKWebView, commitPreviewingViewController previewingViewController: UIViewController)
當(dāng)用戶觸摸元素時(shí)webView(_:shouldPreviewElement:)立即被調(diào)用。返回false將完全禁用該元素的預(yù)覽,并且阻止其他方法的調(diào)用。返回true將提供一個(gè)自定義視圖控制的機(jī)會(huì),前提是用戶觸摸時(shí)有足夠的力度來(lái)啟動(dòng)查看。
如果用戶輸入Peek,那么webView(_:previewingViewControllerForElement:defaultActions:)為其提供了一個(gè)定制視圖控制器的機(jī)會(huì)。返回任何非空視圖控制器都會(huì)導(dǎo)致視圖控制器顯示為Peek預(yù)覽。defaultActions參數(shù)是一個(gè)活動(dòng)數(shù)組,WebKit 默認(rèn)使用它作為previewActionItems。如果想要使用這些活動(dòng)中的任何一個(gè),你只需從視圖控制器的previewActionItems執(zhí)行結(jié)果中返回即可。
如果用戶用足夠的力觸摸來(lái)彈出視圖控制器,webView(_:commitPreviewingViewController:)將被調(diào)用。
3.Swift與JS交互
動(dòng)態(tài)加載并運(yùn)行JS代碼
// js代碼片段
let jsStr = "var checkBtn = document.getElementsByClassName('check_box');for(var j = 0;j < checkBtn.length; j++){checkBtn[j].onclick = function(){this.removeAttribute('checked');}}"
// 根據(jù)JS字符串初始化WKUserScript對(duì)象
let userScript = WKUserScript(source: jsStr, injectionTime:.atDocumentEnd, forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)
// 根據(jù)生成的WKUserScript對(duì)象,初始化WKWebViewConfiguration
let webConfiguration = WKWebViewConfiguration()
webConfiguration.userContentController = userContentController
let userWebview = WKWebView(frame: CGRect.zero, configuration: webConfiguration)
view.addSubview(userWebview)
webView 執(zhí)行JS代碼
用戶調(diào)用JS代碼,一般指服務(wù)端開(kāi)發(fā)的:
webView .evaluateJavaScript(<#T##javaScriptString: String##String#>, completionHandler: <#T##((Any?, Error?) -> Void)?##((Any?, Error?) -> Void)?##(Any?, Error?) -> Void#>)
JS 調(diào)用 Native APP
-
WKScriptMessageHandler
這個(gè)協(xié)議中包含一個(gè)必須實(shí)現(xiàn)的方法,這個(gè)方法是提高App與web端交互的關(guān)鍵,它可直接將接收到的JS腳本轉(zhuǎn)為Swift對(duì)象。
// 從web界面中接收到一個(gè)腳本時(shí)調(diào)用
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
1.首先添加WKScriptMessageHandler代理
extension ViewController:WKScriptMessageHandler
2.實(shí)現(xiàn)userContentController的代理方法
func userContentController(userContentController: WKUserContentController!, didReceiveScriptMessage message: WKScriptMessage!) {
if(message.name == "callbackHandler") {
println("JavaScript is sending a message \(message.body)")
}
}
3.WebView啟動(dòng)對(duì)JavaScript的監(jiān)聽(tīng)事件
contentController.addScriptMessageHandler(
self,
name: "callbackHandler"
)
4.在H5中,添加如下js
webkit.messageHandlers.callbackHandler.postMessage("Hello, webkit!");