前语

跟着移动互联网的快速开展,Web开发与原生运用开发的边界正逐步变得模糊。一方面,Web技能在不断的进步,许多从前只能在原生运用中完成的功能,如离线存储、设备API访问等,现在现已能够经过Web技能完成。另一方面,原生运用开发也开始选用Web技能,以提高开发功率和完成跨渠道的才能。这种将Web开发与原生开发结合的趋势,为移动运用开发带来了全新的或许。

UIWebView与WKWebView的更迭

最初,iOS渠道上加载网页的办法是经过运用UIWebView。然而,跟着iOS渠道技能的开展,UIWebView的局限性逐步显现。首先,UIWebView的功能问题杰出,它在加载网页时需求消耗大量的内存和CPU资源,导致运用运转功率低下。其次,UIWebView不支持并发加载多个网页,这在多任务处理的场景下显得无能为力。最终,UIWebView的API规划较为陈旧,不支持新的Web技能标准。

为了解决这些问题,苹果在iOS 8中引进了一个新的组件——WKWebView,用来取代UIWebView。WKWebView在规划时选用了Nitro JavaScript引擎,这是一个高效的引擎,能大大提高JavaScript的履行功率。一起,WKWebView还支持并发加载多个网页,并且选用了最新的Web技能标准,使得开发者能够运用最新的Web技能。

WKWebView与JavaScript的交互原理

WKWebView与JavaScript的交互,基本上能够分为两个方向:一是JavaScript调用Swift代码,二是Swift代码调用JavaScript代码。

关于JavaScript调用Swift代码,WKWebView供给了WKScriptMessageHandler协议,开发者能够经过完成该协议的userContentController(_:didReceive:)办法,来接纳JavaScript代码经过postMessage办法发送过来的音讯。

关于Swift代码调用JavaScript代码,WKWebView供给了evaluateJavaScript(_:completionHandler:)办法,开发者能够经过这个办法履行JavaScript代码,并经过completionHandler获取履行成果。

接下来经过一个例子来运用WKWebView与JavaScript的交互

1. 创立和装备WKWebView

首先,咱们需求创立一个Swift项目,在默许生成ViewController中引进WebKit模块,用于对WKWebView运用的支持。

import WebKit

让ViewController完成WKNavigationDelegate和WKScriptMessageHandler协议。WKNavigationDelegate协议用于处理网页导航事件,WKScriptMessageHandler协议则用于接纳JavaScript发送的音讯。此外,声明一个WKWebView类型的变量webView。

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
     var webView: WKWebView!;
     ...
}

loadView办法中,咱们首先创立了一个WKUserContentController实例,并经过add(self, name: "nativeCallback")办法添加了一个名为”nativeCallback”的message handler。然后,咱们创立了一个WKWebViewConfiguration实例,并将其userContentController特点设置为咱们方才创立的content controller。最终,咱们运用这个装备对象来创立WKWebView的实例,并将其赋值给view控制器的view特点。

override func loadView() {
    let contentController = WKUserContentController();
    contentController.add(self, name: "nativeCallback")
    let config = WKWebViewConfiguration();
    config.userContentController = contentController;
    webView = WKWebView(frame: .zero, configuration: config);
    webView.navigationDelegate = self;
    view = webView;
}

留意由于这里没有在Interface Builder中运用Storyboard或Xib文件定义了视图的布局,因而需求重写loadView办法,在这个办法中,需求创立一个UIView(或其子类)的实例,并赋值给视图控制器的view特点。

viewDidLoad办法中,咱们创立了一个URL请求,并经过webView.load(myRequest)办法加载这个请求,用于加载本地服务器上的index.html文件

override func viewDidLoad() {
    super.viewDidLoad()
    let myURL = URL(string: "http://127.0.0.1:8080")
    let myRequest = URLRequest(url: myURL!)
    webView.load(myRequest)
}

2. 处理JavaScript调用

userContentController(_:didReceive:)办法中,咱们处理了JavaScript代码发送的音讯。当JavaScript代码经过window.webkit.messageHandlers.nativeCallback.postMessage(message)调用”nativeCallback”的message handler时,这个办法就会被调用。咱们在这个办法中查看音讯的内容,并显现一个alert对话框。

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "nativeCallback" {
        if let msg = message.body as? String {
            showAlert(message: msg)
        }
    }
}
func showAlert(message: String) {
    let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
    let okAction = UIAlertAction(title: "确认", style: .default, handler: nil)
    alertController.addAction(okAction)
    present(alertController, animated: true, completion: nil)
}

3. 调用JavaScript办法

在WKNavigationDelegate的webView(_:didFinish:)办法中,咱们调用了JavaScript的displayDate()办法来显现当时的日期。

swiftCopy code
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("displayDate()") { (any, error) in
        if (error != nil) {
            print(error ?? "err")
        }
    }
}

上述代码中在WKWebView加载完index.html页面后,swift会调用index.html的js办法displayDate()办法来显现当时的日期。

4. Web页面

在index.html页面中,咱们定义了两个JavaScript函数:displayDate()nativeCallback()displayDate()函数会将当时的日期显现在id为”date”的p元素中。nativeCallback()函数会经过webkit.messageHandlers.nativeCallback.postMessage('js调用ios')发送一个音讯到原生运用。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
    <title>wkwebview</title>
    <style type="text/css">
    	h1 {
	    	color: red;
	    	font-size: 1em;
		}
		body {
		    font-size: 2em;
		}
		button {
		    font-size: 0.5em;
		}
		p {
			font-size: 0.5em
		}
		#tip {
			color: blue;
		}
    </style>
</head>
<body>
    <h1>WKWebview和JS交互</h1>
    <div>
    	<p id="tip">ios调用js显现日期:</p>	
    	<p id="date">这是一个段落</p>	
    </div>
    <button type="button" onclick="nativeCallback()">js调用ios</button>
    <script type="text/javascript">
        function displayDate(){
            document.getElementById("date").innerHTML=Date();
        }
        function nativeCallback() {    
            try {
              //运用此办法,会报错,因而运用try-catch
              webkit.messageHandlers.nativeCallback.postMessage('js调用ios');
            } catch(error) {
              console.log('WKWebView post message error: ', error);
            }
        }
    </script>
</body>
</html>

经过上面4个过程后,能够得到成果,当WKWebView加载页面成功后,对调用index.htmldisplayDate()办法来显现时间,点击页面上的按钮会弹出提示弹窗

IOS: WKWebView和JS交互

以上就是在IOS中运用WKWebViewJavaScript进行交互的基本过程。这种交互办法为原生供给更大的灵活性,咱们能够利用Web技能的便利性,一起保持原生运用的高功能和流畅性。

需求留意的是,尽管WKWebView供给了一套完好的API来和JavaScript进行交互,但咱们依然需求谨慎处理JavaScript发送的音讯,避免潜在的安全问题。在实际开发中,咱们应该尽量限制JavaScript能够调用的原生办法,并对传递的数据进行严格的验证和过滤。

一起,咱们也需求留意WKWebView的功能问题。尽管WKWebView的功能大大优于UIWebView,但它依然不如原生视图。因而,应该根据运用的具体要求和功能要求,合理挑选运用WKWebView和原生视图。