随着移动互联网进入下半场,App开发也不再局限与Native开发,或多或少都要用到H5技术,完全以H5技术来构建App的框架也越来越多,比较有代表性的React Native、Flutter。
在这个发展过程中,Native与H5擦出些小火花是不可避免的,接下来就来聊聊他们之间的你来我往、爱恨纠缠!
OC调用JS
- 不需要JavaScriptCore.framework框架
[self.webview stringByEvaluatingJavaScriptFromString:@"js代码字符串"];
- 需要JavaScriptCore.framework框架
三个重要的角色:JSContext、JSValue、JSExport。
JSContext:创建js的上下文,提供js的运行环境;
JSValue:JavaScript和Objective-C数据和方法的桥梁 ,封装了JS与Objc中的对应的类型,以及调用JS的API 等;
JSExport: 这是一个协议,采用协议的方法进行交互的时候,自己定义的协议必须遵守此协议;
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
NSString *jsString = @"JS中的函数名('参数1','参数2')";
[context evaluateScript:jsString];
JS调用OC
1.协议
@protocol 协议名称 <JSExport>
协议方法一
- (void)methodFirst;
协议方法二
- (void)methodSecond;
@end
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// 获取上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"delegate"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue){
context.exception = exceptionValue;
NSLog(@"异常信息:%@",exceptionValue);
};
}
- (void)methodFirst {
//方法实现
......
// 获得想要的结果把结果传回给JS
//获取JS中的函数
JSValue *callBack1 = self.jsContext[@"JS中函数名"];
//把前面获取到的结果作为参数传进JS的callBack参数中
[callBack1 callWithArguments:@[参数1,参数2,...]];
}
- (void)methodSecond {
//方法实现
......
// 获得想要的结果把结果传回给JS
//获取JS中的函数
JSValue *callBack2 = self.jsContext[@"JS中函数名"];
//把前面获取到的结果作为参数传进JS的callBack参数中
[callBack2 callWithArguments:@[参数1,参数2,...]];
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="margin-top: 20px">
<h2>JS与OC交互</h2>
<input type="button" value="JS直接调用OC方法 methodFirst" onclick="delegate.methodFirst()">
</div>
<div>
<input type="button" value="JS直接调用OC方法 methodFirst" onclick="callSecondMethod()">
</div>
<script>
var callSecondMethod = function() {
//参数
var callInfo = JSON.stringify({"key":"value"});
delegate.methodSecond();// 有参数就传参,无参数就空
}
var CallBack = function (str) {
alert(str);
}
var alertCallBack = function(str) {
alert(str);
}
</script>
2.block
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"约定函数名"] = ^(){
// 获取到的调用“约定方法名”时传递的参数数组
NSArry *args = [JSContext currentArguments];
for(JSValue *jsVal in args){
NSLog(@"%@",jsVal.toString);
}
__block JSContext *contextObject = context;
dispatch_async(dispatch_get_main_queue(), ^{
UI操作
NSString *jsStr = @"js函数名('传递返回值')";
[contextObjet ealuateScript:jsStr];
});
}
以上就是全部内容。
今天利用以上技术点写了一个H5调用系统相册的小插件,详情:【Demo】(https://github.com/UnclenamedJack/js-oc)
网友评论