纯牛奶645
纯牛奶645
  • 发布:2016-11-30 16:16
  • 更新:2020-11-11 17:48
  • 阅读:2944

使用JavaScriptCore 实现OC与JS的交互

分类:Native.js

一、说明这篇文章记录自己在研究OC与JS交互中的所得,以及遇到的问题与解决
由于苹果的审核时间太漫长,一次审核不过,那又将进入另一个漫长的审核期。为了能在开发中方便更新,公司要求在项目中使用HTML5,这样就涉及到OC与JS的交互,不懂H5,不懂JS。在经过一段时间的摸索之后,将自己的研究记录下来,以做备忘。
OC与JS的交互实现方式有很多,之前用的比较多的是WebViewJavaScriptBridge,但在IOS7之后,苹果将JavaScriptCore框架开放。因此,这篇文章不讲理论,主要讲的是JavaScriptCore的实际使用。
文中所用的项目JavaScriptCoreDemo
废话说完了,下面进入正题

二、Demo项目中功能介绍

Demo首页
这个demo主要分为了三个部分来:
1.JS Call OC , JS调用OC的函数
2.OC Call JS , OC调用JS的函数
3.一个绘图的例子

在做OC与JS交互工作之前,我们需要做些准备工作
1.导入JavaScriptCore的头文件

import <JavaScriptCore/JavaScriptCore.h>

2.用webView加载HTML文件,这里用的是本地HTML;
[Objective-C] 查看源文件 复制代码
?
01
02
03
04
05
06
07
08
09
10

  • (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.title = @"js call oc";

NSString path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"JSCallOC.html"];
NSURLRequest
request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];
[self.webView loadRequest:request];
}

3.在JS交互中,很多事情都是在webView的delegate方法中完成的,通过JSContent创建一个使用JS的环境,所以这里,我们先将self.content在这里面初始化;
[Objective-C] 查看源文件 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13

  • (void)webViewDidFinishLoad:(UIWebView *)webView
    {
    //初始化content
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

// 打印异常,由于JS的异常信息是不会在OC中被直接打印的,所以我们在这里添加打印异常信息,
self.context.exceptionHandler =
^(JSContext context, JSValue exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
};
}

三、实际操作中 JS call OC先来看demo

JS Call OC

这个页面整个都是通过HTML实现的,
1 计算阶乘:在输入框中输入一个数字,然后在OC中计算出结果,最后显示在HTML的页面上;
2 测试log:点击后,在后台打印测试数据;
3 OC原生Alert :点击后,弹出OC的提示框;
4 addSubView:点击后,在OC中添加一个View;
5 push to second ViewController :跳转到下一个界面
总结:以上功能都是在OC获取HTML中按钮的点击事件,在后在OC中实现功能.

??如何获取HTML中的点击事件呢??
在HTML中,为一个元素添加点击时间有两种写法
<input type="button" value="计算阶乘" />或者
<input type="button" value="测试log" />
如果是第一种方法,那么就要用JSExport协议关联native的方法,要在webView的delegate里面添加
// 以 JSExport 协议关联 native 的方法self.content[@"native"] = self;添加完之后,要声明一个继承JSExport的协议,协议中声明供JS使用的OC的方法
[Objective-C] 查看源文件 复制代码
?
01
02
03
04
05
06
07
08
09
10
@protocol TestJSExport <JSExport>
JSExportAs
(calculateForJS /* handleFactorialCalculateWithNumber 作为js方法的别名 /,

  • (void)handleFactorialCalculateWithNumber:(NSNumber *)number
    );
    • (void)pushViewController:(NSString )view title:(NSString )title;

-(void)log:(NSString*)l;

@end

在OC中实现这些方法,这样就完成了!

如果是第二章方法,则只需要通过block的形式关联JavaScript function就可以了
!self.context[@"log"] = ^(NSString *str){NSLog(@"%@", str);};

三、OC调用JS

OC调用JS

在这个例子中,界面的所有View都是OC创建的,点击“交给JS处理计算阶乘”后,将textfild的数据传给JS,JS计算完成后在返回来!
这里面首先要获取JS里面的计算函数,在OC中,所有表示JS中对象,都用JSValue来创建,通过objectForKeyedSubscript方法或者直接使用下标的方法获取JS对象,然后使用callWithArguments方法来执行函数
[Objective-C] 查看源文件 复制代码
?
1
2
3
4
5
// 方法一. JSValue function = [self.context objectForKeyedSubscript:@"factorial"];
// 方法二.
JSValue
function = self.context[@"factorial"];
JSValue *result = [function callWithArguments:@[inputNumber]];
self.showLable.text = [NSString stringWithFormat:@"%@", [result toNumber]];

四、demo之外(慢慢在总结)1.JS注入
2.在OC中为JS创建对象
......

零碎的补充1:对于JS 函数中,参数中有函数的,在OC中用JSValue接收
[Objective-C] 查看源文件 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
// 比如:JS代码[/font] function myFunc({"text":"这里是文字","callbackFun":function(string){alert'string'}});

//OC代码中在.h的protocol中声明JS要调用的OC方法
//.h protocol中,函数名称要和JS中相同,这里接收的参数为JSValue
JSExportAs
(myFunc,
-(void) myFunc:(JSValue*)value
);

//在.m文件中,实现myFunc方法
-(void) myFunc:(JSValue*)value{

NSString * text = [value valueForProperty:@"text"];//打印"这里是文字"

JSValue * func = [value valueForProperty:@"callbackFun"]; //这里是JS参数中的func;

//调用这个函数
[func callWithArguments:@[@"这里是参数"]];

}

demo 直接下载:
[pan=https://github.com/shaojiankui/JavaScriptCore-Demo/archive/master.zip]|10[/pan]

1 关注 分享
2***@qq.com

要回复文章请先登录注册

hellobugs

hellobugs

回复 赵梦欢 :
他这是哪里拷贝黏贴过来的,都懒得编辑
2020-11-11 17:48
hellobugs

hellobugs

他这是哪里拷贝黏贴过来的
2020-11-11 17:47
赵梦欢

赵梦欢

建议使用markdown语法对内容进行编辑更有利于读者阅读。
2016-11-30 17:26