预置对象
前面我们讲过,WebView 启动时,客户端就向 JS 预置了一些方法,比如:
let data = ...
window.webkit.messageHandlers.iOSBridge.postMessage(data)
iOS 的 WKWebView 的 window 下,预置了messageHandlers
,而我们通过 native 代码又可以预置iOSBridge
对象,
这个对像包含了postMessage
方法用于调用 native
那么如何实现呢
WKWebView添加userContentController
修改 ViewController 的代码,如下:
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
// 添加一个Handler,名字为iOSBridge
config.userContentController.add(BridgeHandler(), name: "iOSBridge")
webView = WKWebView(frame: self.view.frame, configuration: config)
webView.uiDelegate = self
self.view.addSubview(webView)
let url = URL(string:"https://www.baidu.com")!
let request = URLRequest(url: url)
webView.load(request)
}
}
// 创建一个类,继承WKScriptMessageHandler。
// 注意:这里需要继承NSObject,暂不说明
class BridgeHandler : NSObject, WKScriptMessageHandler {
// 当js调用这个bridge对象时,这个方法会被调用
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage)
{
print("WebView callNative ok.")
}
}
js 端调用:
window.webkit.messageHandlers.iOSBridge.postMessage("Hello");
接下来我们要添加一个 HTML 页面,让上面这段 JS 运行起来
创建自己的网页
在写完以上代码后,我们需要测试代码运行情况。但是我们加载的是 baidu.com,没发运行我们的 js 代码, 因此我们需要自己的网页。
我们有两种方式:
- 起一个临时的服务器,比如:http://localhost:8080/test.html
- 直接将网页写到 iOS 项目中
为方便理解 iOS 加载项目中的网页,我们采用第 2 中方式
创建 html 文件
首先,新建 test.html 文件
创建完后添加如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
button {
display: block;
width: 100%;
height: 30%;
font-size: 50px;
}
</style>
</head>
<body>
<script type="text/javascript">
function onClickButton() {
// 出现了,我们调用native的代码
window.webkit.messageHandlers.iOSBridge.postMessage("Hello");
}
</script>
<!-- 打算点击按钮调用native -->
<button onclick="onClickButton()">Call Native</button>
</body>
</html>
最后,ViewController 中的加载百度的代码改为:
// 获取项目中的test.html的url
let url = Bundle.main.url(forResource: "test", withExtension: "html")!
// 使用loadFileURL
webView.loadFileURL(url, allowingReadAccessTo: url)
注意:上面不再使用 load(request)了,而是本地路径
运行
运行前了解一下 XCode 的Console
面板:
说明:
- 面板开关按钮
- 日志输出按钮
运行后,多点几次 Call Native 按钮就会得到第 2 点的输出,说明你已经完成了JS调用Native
。
兼容性:
MacOSX 10.15.X 版本系统运行调试程序,日志窗口不停的打 log
[Process] kill() returned unexpected error 1
解决方案:
- Xcode menu 打开: Product > Scheme > Edit Scheme
- 在 Environment Variables 添加设置 OS_ACTIVITY_MODE = disable
- 重新 Run 程序
附图: