本文详解如何在iOS7及以上版本中使用JavaScriptCore框架实现Objective-C与JavaScript的双向通信。通过UIWebView加载本地HTML,利用JSContext捕获JS调用并传递参数,同时通过evaluateScript方法由OC主动调用JS函数,涵盖无参及有参调用的完整实现方案。
JavaScriptCore简介
JavaScriptCore
JavaScriptCore是WebKit引擎的核心组件之一,主要负责JavaScript代码的解析与执行环境的提供。自iOS7起,苹果在iPhone平台上引入该框架,极大地简化了原生代码与JavaScript之间的交互操作。
环境初始化
首先,需要创建UIWebView实例,并加载本地的HTML文件。
NSURL* htmlURL = [[NSBundle mainBundle] URLForResource: @"demo" withExtension: @"html"];
[_webView loadRequest: [NSURLRequest requestWithURL: htmlURL]];
交互场景概览
在本示例中,我们将演示四种常见的交互场景。
- JS调用OC方法
- JS调用OC方法并传递参数
- OC调用JS方法
- OC调用JS方法并传递参数
HTML文件中的代码如下所示。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function showAlert(){
alert('OC call JS with no argument');
}
function showAlertWithString(string){
alert(string);
}
function callOCWithArgument() {
jsCallOCWithArgument('参数1 ','参数2 ','参数3');
}
</script>
</head>
<body>
</br>
</br>
</br>
</br>
<form>
<button type='button' onclick='callOC()'>jsCallOC</button>
<button type='button' onclick='callOCWithArgument()'>jsCallOCWithArgument</button>
</form>
</body>
</html>
JS调用OC实现
JS调用OC的实现方式。
在UIWebView的代理方法webViewDidFinishLoad中,
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
_context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
__weak typeof(self) weakSelf = self;
_context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
weakSelf.context.exception = exception;
};
//js调用OC
_context[@"callOC"] = ^() {
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal.toString);
}
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"arguments" message:@"JS Call OC With No Argument" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * action = [UIAlertAction actionWithTitle:@"Done" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[alertView addAction:action];
[weakSelf presentViewController:alertView animated:YES completion:nil];
});
};
_context[@"jsCallOCWithArgument"] = ^() {
NSArray *args = [JSContext currentArguments];
NSMutableString * stirng = [NSMutableString string];
for (JSValue * value in args) {
[stirng appendString:value.toString];
}
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"arguments" message:stirng preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * action = [UIAlertAction actionWithTitle:@"Done" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[alertView addAction:action];
[weakSelf presentViewController:alertView animated:YES completion:nil];
});
};
}
我们定义一个Block并将其保存到JSContext中,这实际上是将该Block转换为JS中名为callOC的函数。随后直接执行该函数,即可触发Block内部定义的内容。
接收到的参数可以通过[JSContext currentArguments]数组获取,其中包含JSValue对象。
OC调用JS实现
OC调用JS的实现方式。
初始化两个Button控件,并在其点击事件中实现以下方法。
- (IBAction)callJS:(id)sender {
[_context evaluateScript:@"showAlert()"];
}
- (IBAction)callJSWithArguments:(id)sender {
[_context evaluateScript:@"showAlertWithString('OC call JS with arguments')"];
// [_context[@"showAlertWithString"] callWithArguments:@[@"OC call JS with arguments"]];
}
通过上述代码即可实现OC对JS的调用。
完整Demo已上传,有需要的读者可点击此处下载查看。
总结
以上就是本文的全部内容,希望这些内容能对大家的编程学习或工作有所帮助。如有任何疑问,欢迎在评论区留言交流。