JavaScriptCore框架使用



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

JavaScriptCore框架使用_第1张图片
这里写图片描述

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

#import

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

 #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的键获取到JSContext)
 JSContext *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文件




  
       
       //引入js
  SimonLike


//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 

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

@end
 

2,新建一个类对象,实现协议和方法,例:
person.h


#import "JSExportTest.h"

@interface person : NSObject
@end

person.m

#import "person.h"

@implementation person
- (NSString *)personName{
    return @"this is OC";
}
@end

3,js方法调用

-(void)jsJSExport {

    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); 
};

你可能感兴趣的:(JavaScriptCore框架使用)