使用WebViewJavascriptBridge实现iOS与js交互
背景: 原生应用跳转到 h5 页面, 并实现原生与 h5 页面的交互, 比如在 h5 页面中调用原生的拨打电话、拍照、选文件、定位等功能
iOS 端集成 WebViewJavascriptBridge
安装
方式一: 使用CocoaPods
集成:
1 | pod 'WebViewJavascriptBridge', '~> 6.0' |
方式二: 手动集成, 把源代码WebViewJavascriptBridge
文件夹拖到项目里. 我采用的是这种方式, 方便修改源码.
注意: 2020 年 4 月起 App Store 将不再接受使用
UIWebView
的新 App 上架、2020 年 12 月起将不再接受使用UIWebView的App
更新。而该库中WebViewJavascriptBridge
文件是对UIWebView
的处理, 所以项目中把WebViewJavascriptBridge
文件删除.
使用
初始化WebViewJavascriptBridge
对象
- 导入
WKWebViewJavascriptBridge
1
#import "WKWebViewJavascriptBridge.h"
- 声明属性
1
@property(nonatomic, strong) WKWebViewJavascriptBridge *bridge;
- 初始化
1
self.bridge = [WKWebViewJavascriptBridge bridgeForWebView:self.wkWebView];
- 设置代理, 自由实现
WKNavigationDelegate
方法1
[self.bridge setWebViewDelegate:self];
- 开启日志
1
[WKWebViewJavascriptBridge enableLogging];
iOS 调用 js 方法
- js 端先注册方法
1
2
3
4bridge.registerHandler("JS Echo", function (data, responseCallback) {
console.log("JS Echo called with:", data);
responseCallback(data);
}); - iOS 端调用
1
2
3[self.bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) {
NSLog(@"ObjC received response: %@", responseData);
}];
js 调用 iOS 方法
- iOS 端先注册方法
1
2
3
4[self.bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"ObjC Echo called with: %@", data);
responseCallback(data);
}]; - js 端调用
1
2
3bridge.callHandler("ObjC Echo", { key: "value" }, function responseCallback(responseData) {
console.log("JS received response:", responseData);
});
JS 端使用
桥接文件
针对 iOS 建立连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement("iframe");
WVJBIframe.style.display = "none";
WVJBIframe.src = "https://__bridge_loaded__";
document.documentElement.appendChild(WVJBIframe);
setTimeout(function () {
document.documentElement.removeChild(WVJBIframe);
}, 0);
}针对 Android 建立连接方法
1
2
3
4
5
6
7
8
9
10
11
12
13function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(window.WebViewJavascriptBridge);
} else {
document.addEventListener(
"WebViewJavascriptBridgeReady",
() => {
callback(window.WebViewJavascriptBridge);
},
false
);
}
}适配 iOS 和 android 的桥接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22let ua = navigator.userAgent;
let android = /(Android);?[\s\/]+([\d.]+)?/.test(ua);
let ios = /\(i[^;]+;( U;)? CPU.+Mac OS X/.test(ua);
function hybridBridgeReady(ready) {
if (ios) {
setupWebViewJavascriptBridge(ready);
} else if (android) {
connectWebViewJavascriptBridge(ready);
}
}
if (android) {
hybridBridgeReady((bridge) => {
bridge.init((message, responseCallback) => {
let data = {
documentReady: "ready",
};
responseCallback(data);
});
});
}js 端注册方法供原生端调用
1
2
3
4
5
6hybridBridgeReady((bridge) => {
bridge.registerHandler("JS Echo", function (data, responseCallback) {
console.log("JS Echo called with:", data);
responseCallback(data);
});
});js 端调用原生端方法
1
2
3
4
5hybridBridgeReady((bridge) => {
bridge.callHandler("ObjC Echo", { key: "value" }, function responseCallback(responseData) {
console.log("JS received response:", responseData);
});
});
参考文档