iOS 基础--JavaScriptCore简单总结

<big><b>红酥手,黄藤酒,满城春色宫墙柳!</b></big><伊布>

  • 苹果在 iOS7中增加了 JavaScriptCore 框架,而这个框架正是大大的简化 JavaScript 与 Objective-C之间的交互!它把 WebKit 的 JavaScript 引擎用 Objective-C 封装,我们可以用很简便的方法快速的接入当下流行的 JavaScript。
  • JavaScriptCore可以让我们在 OC 执行的代码的任何地方运行JS 代码,不依赖 WebView
  • JavaScriptCore主要就是给我们提供了 JS 代码的执行环境并进行解析运行
  • 让我们应用扩展性大大提高,提供了动态去修改我们局部代码或者逻辑的思路(实现热更新),同时让我们去嵌入网页并加以调整变得轻松。

简单的总结一下关于这个框架基础使用,才浅学薄欠缺之处望包含指正!

  • JSContext

它是 JavaScript 代码的运行环境,也就是作用的范围。每一个 JSContext 就是一个全局的环境变量!我们创建一个 JSContext 对象之后,可以利用它去执行相应的JavaScript 的代码操作(创建变量,定义方法等)!

  • JSValue

它是为了处理 Objective-C 对象(强类型)和 JavaScript 对象(弱类型)差异的类,实现 OC 和 JS 对象的相互转化。在处理的时候 JSValue对象包裹着来自 JSContext 的值例如字符串、对象甚至是方法、还有一些错误的特殊的 JS 值类似 null 和 undefined。这个类的一些列方法(得到 Foundation 框架下得类型)就是为了我们在 OC 访问这些值时候能够正常的去访问处理!可以理解成是 JS 和 OC 之间互相转换的桥梁,下图是一个简单总结的表格!

JS类型 JSValue转OC Swift 类型 OC 类型 OC 转 JSValue
string toString String! NSString
boolean toBool Bool Bool valueWithBool:inContext:
number toNumberto
toDouble
toInt32
toUInt32
NSNumber!
Double
Int32
UInt32
NSNumber
double
int32_tuint32_t
valueWithDouble:inContext:
valueWithInt32:inContext:
valueWithUInt32:inContext:
Date toDate NSDate! NSDate
Arrar toArray [AnyObject]! NSArray valueWithNewArrayInContext:
Object toDictionary [NSObject : AnyObject]! NSDictionary valueWithNewObjectInContext:
Object toObject
toObjectOfClass:
custom type custom type( id类型) valueWithObject:inContext:
undefined nil nil valueWithUndefinedInContext
null NSNull NSNull valueWithNullInContext:

  • 我们通过代码简单理解一下 OC 和 JS交互简单实现
  • 创建JSContext 对象
JSContext *context = [[JSContext alloc] init];```
 - 用这个对象执行 JS 代码得到一个 JSValue 对象
```code
JSValue *jsValue = [context evaluateScript:@"23+6"];```
 - JSValue 值 转换成 OC 的结果值
```code 
int ocValue =  [jsVlaue toInt32];```
 - 执行JS函数(OC中的 Block)这样就相当于下 JS 中调用了 OC 代码
```code
//  就是把这个方法赋给 JS 的 log 这个属性(没有的话JS 会自动创建这个属性)
  context[@"log"] = ^(NSInteger value){
        NSLog(@"-------->%ld",value);// 这里打印了掺入的第一个传入的参数
        // 处理传进来的参数
        NSArray *arr = [JSContext currentArguments]; // 返回一个数组 获取到的是 JS 传进去的不定参数
        for (id item in arr) {
            NSLog(@"--->%@",item);// 依次打印了传进来的参数
        }
    };
// 执行 JS 代码
    [context evaluateScript:@"log(11,2,3)"];```


![打印结果](http://upload-images.jianshu.io/upload_images/1523603-76924e82a8ecc542.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

 - 我们也可以在 OC 中使用 JS 代码结果
  - 小例子:这里我写一个求 1->n 和 以及 N 阶乘 的 JS 代码然后执行结果转成 OC 的
```code
 JSContext *context = [[JSContext alloc] init];
# 这里是 JS 求和以及计算阶乘的代码
 [context evaluateScript:@"var numSum = function(n){var sum = 0;  for( i = 0;i <= n;i++ ){ sum += i; } return sum };var factorial = function(n) { if (n < 0) return; if (n === 0) return 1; return n * factorial(n - 1) };"];
    JSValue *function = context[@"numSum"];
# 调用 JS 函数方法,并返回函数的结果 传入的参数是一个给函数的传递的参数放到数组里面
    JSValue *numSum = [function callWithArguments:@[@5]];
    NSLog(@"把 JS结果转化成 OC结果---->%d",[numSum toInt32]);```

![打印结果](http://upload-images.jianshu.io/upload_images/1523603-b0c193583da713ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
--------

-----
- 再写一个简单的例子,我们在利用 OC 的WebView 加载 一个网页,网页上有一个 Button,点击这个 Button 我们 iOS 客户端相应的进行一些操作也就是 OC 和 HTML 交互!
 -  一个简单的 HTML 代码
 ```code
 <!DOCTYPE html>
 <html>
    <head>
        <meta charset="UTF-8">
            <title></title>
            </head>
    <body>
        <input type="button" value="login" onclick="log()" />
    </body>
</html>
  • 我们用 WebView 加载这个 HTML
UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectMake(10, 10, 300, 500)];// 创建
    [self.view addSubview:webview];// 添加父视图
    webview.delegate = self;// 设置代理
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];// 找到要加载的 HTML 文件
    NSString *urlStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    [webview loadHTMLString:urlStr baseURL:nil];// 加载``` 
 - 我们在代理方法中获取这次加载
```code
     // 每次加载网页请求都会走该方法 
     - (void)webViewDidFinishLoad:(UIWebView *)webView
 {// 获取当期WebView 相关的 context,获取 JS执行环境
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 我们把点击的事件获取到 也就实现了效果
     context[@"log"] = ^(){
        NSLog(@"点击了网页上那个的 Button!")
}```

![结果打印.gif](http://upload-images.jianshu.io/upload_images/1523603-f3dfcdb6119cfa22.gif?imageMogr2/auto-orient/strip)

- JSExport
> 要想在 JS 中调用OC 对象的方法和属性,需要把这些属性方法放到继承于 JSExport 的协议中,因为只有JSExport 协议中的方法才能被 JavaScript 识别!OC 对象相应的实现协议方法!

 - 代码示例我们先定义一个协议
```code
// 一定要继承于 JSExport
@protocol JS_OC_Delegate <JSExport>
@property (nonatomic, strong) NSString *name;
@end```
   - 在一个类中(这里是在 ViewController)中遵循代理并实现方法
```code
@synthesize name;```
   - 转化执行
```code
  self.name = @"云之君兮鹏";
    JSContext *context = [[JSContext alloc] init];
    context[@"OC_Object"] = self;
    [context evaluateScript:@"OC_Object.name = '小超人'"];
     NSLog(@"%s--->%@",__func__,self.name);

打印结果

  • 注意一些问题:

  • 不要在Block 中直接引用使用外面的 JSContext 对象,应该用·[JSContext currentContext];

  • 同样的不要直接在 Block 中调用外界的 JSValue 对象,需要的话可以利用参数传递进去。
    - 原因(我们在 OC 中经常回去注意的问题,避免了循环引用,相互持有!Block 可以保有变量引用,而且 JSContext 也强引用它所有的变量。)

  • 当我们使用JS 调用 OC 的回调方法时,均是在子线程中执行的,这样的话我们得注意需要的时候,要回到主线程去更新我们 UI 界面。

JSContext *context = [[JSContext alloc] init];
    context[@"函数名"] = ^(类型 参数){
# 尴尬了 循环引用
JSValue *value =  [JSValue valueWithNewObjectInContext:context];
# 顾德乐 正常使用
JSValue *value =  [JSValue valueWithNewObjectInContext:[JSContext currentContext]];
    };

今天先到这了,日后补充更新,开心就好!对了简友们节日快乐!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容