1.js调用oc的方法(vue && 原生html)
(1.1)创建webview的时候注册js要用到的方法
- (WKWebView *)webview{
if (!_webview) {
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
// 注册js要调用的方法(requireIOSToken)
[wkUController addScriptMessageHandler:self name:@"requireIOSToken"];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = wkUController;
_webview = [[WKWebView alloc] initWithFrame:CGRectMake(0, kNavBarHeight, kScreenWidth, kScreenHeight - kNavBarHeight) configuration:config];
// _webview = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:webConfig];
_webview.allowsBackForwardNavigationGestures = YES;
_webview.UIDelegate = self;
_webview.navigationDelegate = self;
_webview.scrollView.delegate = self;
// 禁止网页边缘反弹
// _webview.scrollView.bounces = NO;
_webview.scrollView.mj_header = self.refreshHeader;
if (@available(iOS 11.0, *)) {
_webview.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = false;
}
}
return _webview;
}
(1.2)遵守WKScriptMessageHandler协议
@interface WebViewController ()<WKScriptMessageHandler>
(1.3)实现WKScriptMessageHandler代理方法
#pragma mark - WKScriptMessageHandler ---- 监听js调用oc的方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if([message.name isEqualToString:@"requireIOSToken"]){
NSDictionary *userDict = @{@"token": @"666666666666"};
// 这里option要使用kNilOptions, 使用NSJSONWritingPrettyPrinted, 前端会识别不了字典对象
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userDict
options:kNilOptions
error:nil];
NSString * jsonDict = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 调用前端的receiveIOSToken方法, 并传递对象:{token : '666666666666'}作为方法参数
NSString *jsString = [NSString stringWithFormat:@"receiveIOSToken('%@')", jsonDict];
// oc调用js的receiveIOSToken方法
[self.webview evaluateJavaScript:jsString completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"result: %@ ----- error: %@", result, error);
}];
}
}
(1.4)普通html发送请求token的方法, 和被oc调用的方法
<!DOCTYPE html>
<head>
<title>JS交互OC</title>
<meta charset="utf-8">
</head>
<body>
<h2 style="text-align:center">js get token</h2>
<p style="text-align:center">
<button id="btn2" type = "button" onclick = "requireIOSToken()"> JS调用OC:带参数 </button>
</p>
<script type = "text/javascript">
// js向oc发送获取token的请求
function requireIOSToken(){
// 可以不传参数
window.webkit.messageHandlers.requireIOSToken.postMessage({"params":"我是参数"});
// window.webkit.messageHandlers.requireIOSToken.postMessage({});
}
// js收到oc发送过来的token
function receiveIOSToken(tokenStr){ // objStr 对象格式 {"token":"666666666666"}
alert("oc 传递的对象为: " + tokenStr);
}
</script>
</body>
</html>
(1.5)上述方法放在vue会报找不到receiveIOSToken的错误. 原因是,使用vue的话,需要将oc要调用的方法预先挂载到window的created生命周期去
// 在vue中,只需要将方法绑定到window中即可,ios就能够调用到
created(){
//供iso调用前需要绑定到window上
window.receiveIOSToken = this.receiveIOSToken;
}
mounted(){
// js收到oc发送过来的token
function receiveIOSToken(tokenStr){ // objStr 对象格式 {"token":"666666666666"}
alert("oc 传递的对象为: " + tokenStr);
}
}
2.vue或者html调用oc的方法
// 注:requireIOSToken是ios的方法,params为传递给ios的参数,messageHandlers在电脑浏览器上可能会报错,但是在ios的webkit里面正常,所以这里书写的时候要注意这个方法尽量写在最后,不然后面的代码不能执行,或使用try...catch
window.webkit.messageHandlers.requireIOSToken.postMessage({params :'我是参数'});
3.补充说明, 如果要将字典转成json传递给前端时, 转换的options要使用kNilOptions, 不要使用默认的NSJSONWritingPrettyPrinted, 否则,会报如下的错误:
Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={NSLocalizedDescription=A JavaScript exception occurred
原因是用NSJSONWritingPrettyPrinted输出的结果是
{
"token" : "666666666666"
}
用kNilOptions输出的结果才是json:
{"token":"666666666666"}
NSJSONWritingPrettyPrinted格式转换的json,前端是无法识别的
网友评论