JavaScriptCore

JavaScriptCore框架

iOS 7中苹果正式开放加入了JavaScriptCore框架。该框架让Objective-C和JavaScript 直接进行交互 。这个框架其实只是基于WebKit实现的JavaScriptCore的一个包装

这里写图片描述

要使用JavaScriptCore,首先我们需要引入它的头文件

#import <JavaScriptCore/JavaScriptCore.h>

这个框架主要包括五个对象

 #import "JSContext.h"  //提供运行环境 
 #import "JSValue.h"  //是JSContext执行后的返回结果,他包括多种类型(比如基本数据类型和函数类型,对象类型等)
 #import "JSManagedValue.h" //是JSValue的封装
 #import "JSVirtualMachine.h"  //提供了底层资源
 #import "JSExport.h"   //是一种协议

JSContext对象

在OC中初始化JSContext对象,可以直接init初始化,也可根据当前webView的键获取到jscontext

 // init初始化JSContext对象 
 JSContext *context = [[JSContext alloc] init]; 

 //创建JSContext 对象(通过当前webView的键获取到JSContextJSContext *context=[self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

通过JSContext对象调用js代码,这里是一个弹窗测试:

1.OC直接拼写,实现js弹窗

 NSString *alertJS=@"alert('test js OC')"; //准备执行的js代码
 [context evaluateScript:alertJS];//通过oc方法调用js的alert

2.引入js文件,调用js中的方法,实现js弹窗

//html代码  
//在 index.html中加入js文件
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
       <link rel="stylesheet" type="text/css" href="html/stylesheets/index_css.css" />
       <script type="text/javascript" src='html/js/test.js'></script>//引入js
  <title>SimonLike</title>
</head>

//js代码 
// test.js文件中方法
function jsalert(test){
     alert(test);
}

//OC代码
//在OC中找到html的路径转换格式,用UIWebView进行加载,这个时候js文件、css文件也一起加了进来;
- (void)loadHtml {
   //创建webview
    CGRect webViewRect = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
    self.webView = [[UIWebView alloc] initWithFrame:webViewRect];
    self.webView.backgroundColor = [UIColor lightGrayColor];
    self.webView.scalesPageToFit = YES;
    self.webView.delegate = self;
    [self.view addSubview:self.webView];

   //webview加载html
    NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
    NSURL *url = [NSURL fileURLWithPath:htmlPath];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webView loadRequest:request];
}

//在webview加载完成后,调用js文件中的方法,
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *alertJS=@"jsalert('test js OC')"; //准备执行的js代码
    [context evaluateScript:alertJS];//通过oc方法调用js的alert
}

js调用iOS中OC方法;其中jscandoiOS就是js的方法名称,赋给一个block 里面是iOS代码,注意事项:1,在block中避免循环引用,我们一般会对self进行弱化;2,在block中直接调用OC方法,可能会导致异常或崩溃,所以为了避免异常或崩溃 js调用oc方法时 放在GCD中 进行异步操作;


//OC中拼接,没有加载js文件写法
[context evaluateScript:@"jscandoiOS(tag)"];

//加载js文件写法
function jscandoiOS(tag){
}
 __weak typeof(self)weakSelf = self;//避免循环引用 弱化
     context[@"jscandoiOS"] = ^(JSValue *value){
        NSString *str = value.toString;//把接收到的JSValue对象转换OC中的NSString类型
        dispatch_async(dispatch_get_main_queue(), ^{//在GCD中 进行异步操作
            switch (str.integerValue) {
                case 0:{//iOS  
                 // you can do ...
                }
                    break;
                  ...                 
                default:
                    break;
            }

        });
    };

JSValue对象

上面代码中,点击js方法“jscandoiOS”在iOS中能监听到并做出相应处理,在iOS这边接收到js所传值为JSValue对象,然后转换为OC中的NSString;对于JSValue对象转换OC类型的方法很多:

- (id)toObject;
- (BOOL)toBool;
- (double)toDouble;
- (int32_t)toInt32;
- (NSString *)toString;
- (NSArray *)toArray;
- (id)toObject;
- (NSDictionary *)toDictionary;
...  

JSExport对象

JSExport是一个协议,很方便的让JavaScript能够访问和操作Objective-C对象。

1,自定义个协议(JSExportTest)继承自JSExprot,并定义需要暴露给js的属性和方法,例:
@protocol JSExportTest <JSExport>

- (NSString *)personName;//暴露给js调用

@end
2,新建一个类对象,实现协议和方法,例:

person.h


#import "JSExportTest.h"

@interface person : NSObject<JSExportTest>
@end

person.m

#import "person.h"

@implementation person
- (NSString *)personName{
    return @"this is OC";
}
@end
3,js方法调用
-(void)jsJSExport {
    JSContext *context=[self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    person *p = [[person alloc]init];
    context[@"person"] = p;
    JSValue *value = [context evaluateScript:@"person.personName()"];

    NSLog(@"context->%@",value);
}

打印结果: context->this is OC

JSVirtualMachine对象

一个 JSVirtualMachine可以运行多个context,由于都是在同一个堆内存和同一个垃圾回收下,相互之间传值是没问题的。如果在不同的JSVirtualMachine传值,垃圾回收就不知道他们之间的关系了,可能会引起异常。

JSVirtualMachine有两个方法:一个是保存JSValue对象,一个是移除JSValue对象:

//保存 
- (void)addManagedReference:(id)object withOwner:(id)owner;
//移除 
- (void)removeManagedReference:(id)object withOwner:(id)owner;

JSVirtualMachine对象

引入:http://www.jianshu.com/p/bbfa8dee967e

JavaScriptCore中引入了JSManagedValue类型,该类型主要是作为一个引用桥接,将JSValue转为JSManagedValue类型后,可以添加到JSVirtualMachine对象中,这样能够保证你在使用过程中JSValue对象不会被释放掉,当你不再需要该JSValue对象后,从JSVirtualMachine中移除该JSManagedValue对象,JSValue对象就会被释放并置空。

大家不要被这么多对象类型搞晕了,简单一点说,JSVirtualMachine就是一个用于保存弱引用对象的数组,加入该数组的弱引用对象因为会被该数组retain,所以保证了使用时不会被释放,当数组里的对象不再需要时,就从数组中移除,没有了引用的对象就会被系统释放。

异常处理

context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
    [JSContext currentContext].exception = exception; 
     NSLog(@"exception:%@",exception); 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值