前言
经常看到安卓开发者前端联调,前端一句window.android.方法名(参数)
这样的函数就调用了安卓方法,而ios确非常的麻烦,以前一般我们都是通过在- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler
中拦截url处理。现在,下面介绍另一种WKScriptMessageHandler
方法实现,与安卓类似。
ios端处理
- 使用WKWebView,遵循WKScriptMessageHandler协议
- 创建WKWebView
// oc
- (WKWebView *)wkWebView {
if (!_wkWebView) {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKPreferences *preference = [[WKPreferences alloc] init];
config.preferences = preference;
_wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:config];
_wkWebView.UIDelegate = self;
_wkWebView.navigationDelegate = self;
}
return _wkWebView;
}
// swift
// MARK: 懒加载
lazy var webView: WKWebView = {
let config = WKWebViewConfiguration.init()
let preference = WKPreferences.init()
preference.javaScriptCanOpenWindowsAutomatically = true
config.preferences = preference
let webV = WKWebView.init(frame: CGRect(x: 0, y:20, width: screenW, height: screenH-navH), configuration: config)
webV.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
webV.scrollView.scrollIndicatorInsets = webV.scrollView.contentInset
webV.uiDelegate = self
webV.navigationDelegate = self
return webV
}()
- 注册监听与前端约好的方法名
// oc
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"goHome"];
[self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"goLogin"];
[self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"buyLottery"];
}
// swift
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.webView.configuration.userContentController.add(self, name: "goHome")
self.webView.configuration.userContentController.add(self, name: "goLogin")
self.webView.configuration.userContentController.add(self, name: "buyLottery")
}
- 在页面消失时,记得移除监听
//oc
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"goHome"];
[self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"goLogin"];
[self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"buyLottery"];
self.wkWebView.UIDelegate = nil;
self.wkWebView.navigationDelegate = nil;
}
//swift
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.webView.configuration.userContentController.removeScriptMessageHandler(forName: "goHome")
self.webView.configuration.userContentController.removeScriptMessageHandler(forName: "goLogin")
self.webView.configuration.userContentController.removeScriptMessageHandler(forName: "buyLottery")
self.webView.uiDelegate = nil
self.webView.navigationDelegate = nil
}
- 代理方法中监听前端调用原生的方法
//oc
/// 与js交互
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
// 参数
NSDictionary *body = message.body;
// 约定好的函数名
NSString *name = message.name;
if ([name isEqualToString:@"goHome"]) {
[self.navigationController popViewControllerAnimated:true];
} else if ([name isEqualToString:@"goLogin"]) {
[self.navigationController popViewControllerAnimated:true];
[self.webObj.webViewEngine evaluateScript:@"window.location.href = \"login.html\";localStorage.clear();"];
} else if ([name isEqualToString:@"buyLottery"]) {
[[EUExPrintSdk sharedInstance] printBlueTooth:@[body]];
}
}
// swift
extension XMBaseWebVC: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let body = message.body as? [String:Any]
let name = message.name
XMLog(message: "messageHandler收到的名字为:"+name)
switch name {
case "goHome":
self.goHome()
case "goLogin":
let url = body?["shareUrl"] as? String
let pasteBoard = UIPasteboard.general
pasteBoard.string = url
XMMessageHUD.showMessage(str: NSLocalizedString("复制成功", comment: ""), completion: nil)
case "buyLottery":
let url = body?["url"] as? String
let title = body?["title"] as? String
let content = body?["description"] as? String
let pic = body?["pic"] as? String
XMLog(message: "........")
default:
break
}
}
}
前端js调用
注意:一定要参传数,不然原生是收不到消息
如:
window.webkit.messageHandlers.goHome.postMessage("哈哈"); // 回到首页操作
window.webkit.messageHandlers.goLogin.postMessage("哈哈"); // 跳转到登录面
window.webkit.messageHandlers.buyLottery.postMessage({"mount":"145","oderid":"6d-3891489374893473243","count":"12"}); // 执行买票操作,参数是通过json方法传送,原生是以body方式接收,接收到的是字典
网友评论