笔者将会从UIWebView
和WKWebView
分别讲解。
一. UIWebView篇
先将笔者随手写的一段html
代码贴上来,以供参考。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js与oc交互</title>
<style>
body {
background-color: gray;
}
button {
float: left;
width: 80px;
height: 40px;
}
</style>
</head>
<body>
<!-- <input type="button" value="按钮" onclick="javascrtpt:window.location.href='https://www.baidu.com'"> -->
<button id="btn" onclick="btnClick()">百度</button>
<button id="jscontextbtn" onclick="jsContextMethod('参数1','参数2')">JSContext按钮</button>
<script>
function btnClick() {
window.location.href = 'jsCallOC://www.baidu.com'
}
function jsTest() {
alert('这是一个js方法')
}
function jsTestWithParams(param1) {
alert(param1);
}
</script>
</body>
</html>
1. 通过UIWebView
的协议方法拦截URL
1.1 js调用oc
先创建UIWebView
实例,并加载上面的html
文件。添加UIWebView
的协议@interface ViewController () <UIWebViewDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
self.myWebView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 88, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-88)];
NSString *path = [[NSBundle mainBundle]pathForResource:@"test" ofType:@"html"];
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
[self.view addSubview:self.myWebView];
self.myWebView.delegate = self;
}
点击html
文件的‘百度’按钮,调用function btnClick()
在UIWebView
的协议方法可进行拦截
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = [request URL];//jsCallOC://www.baidu.com
NSString *schem = [url scheme];//jsCallOC
if ([schem isEqualToString:@"jscalloc"]) {
[self jsCallOC];
return NO;
}
return YES;
}
/// js调用oc
-(void)jsCallOC{
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"js调用oc" message:@"点击js方法,调用此oc方法(这是个OC方法)" preferredStyle:UIAlertControllerStyleAlert];
[alertVC addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alertVC animated:YES completion:nil];
}
注意:1.拦截的url是自定义的,可与前端统一好;
2.JS中的‘jsCallOC’,在拦截到的url scheme会全都被转化为小写‘jscalloc’。
3.html 中需要设置编码,否则中文参数可能会出现编码问题。
1.2 OC调用js
在原生页面调用js方法,其中jsTest
是不带参数,jsTestWithParams
带有一个参数(参考上面的html
代码)
-(void)ocCallJS:(UIButton *)btn{
//无参
//NSString *string = [NSString stringWithFormat:@"jsTest()"];
//有参
NSString *string = [NSString stringWithFormat:@"jsTestWithParams('%@')",@"这是个js方法哈哈哈"];
[self.myWebView stringByEvaluatingJavaScriptFromString:string];
}
2 使用JavaScriptCore
库,在iOS 7之后,apple添加了一个新的库JavaScriptCore,用来做JS交互
在项目中添加JavaScriptCore
库,引入头文件#import <JavaScriptCore/JavaScriptCore.h>
JSContext
:js上下文
jsContextMethod
: js中要调用的方法,可以传参过来
2.1 js调用OC
-(void)jsCallOC{
JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"jsContextMethod"] = ^(){
//获取前端方法传过来的参数
NSArray *args = [JSContext currentArguments];//参数
NSMutableString *mutableString = [NSMutableString string];
for (JSValue *jsVal in args) {
NSLog(@"🍎🍎🍎%@",jsVal.toString);
[mutableString appendString:jsVal.toString];
}
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"js调用oc" message:@"点击js方法,调用此oc方法(这是个OC弹框)" preferredStyle:UIAlertControllerStyleAlert];
[alertVC addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alertVC animated:YES completion:nil];
});
};
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
[self jsCallOC];
}
2.2 OC调用js
jsTestWithParams
:js中方法
JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
NSString *textJS = @"jsTestWithParams('这里是JS中alert弹出的message')";
[context evaluateScript:textJS];