美文网首页
JavaScriptCore:OC和JS相互调用(不依赖于Web

JavaScriptCore:OC和JS相互调用(不依赖于Web

作者: LiuffSunny | 来源:发表于2020-05-07 22:14 被阅读0次

    二、在Native中运行JavaScript脚本代码

    我们先来编写一个最简单的例子,使用OC代码来执行一段JS脚本。首先新建一个文件,将其后缀设置为.js,我这里将它命令为main.js,在其中编写如下代码:
    
    (function(){
        console.log("Hello Native");
    })();
    

    上面是一个自执行的函数,其中打印了“Hello Native”字符串。在Native中编写如下代码:

    - (void)viewDidLoad {
        [super viewDidLoad];
        NSString * path = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"];
        NSData * jsData = [[NSData alloc]initWithContentsOfFile:path];
        NSString * jsCode = [[NSString alloc]initWithData:jsData encoding:NSUTF8StringEncoding];
        self.jsContext = [[JSContext alloc]init];
        [self.jsContext evaluateScript:jsCode];
    }
    

    需要注意,其实这里我将创建的JSContext对象作为了当前视图控制器的属性,这样做的目的仅仅是为了方便调试,不过不对此context对象进行引用,当viewDidLoad函数执行完成后,JS运行环境也将被销毁,我们就无法在Safari中直观的看到JS代码的执行结果了。

    运行工程,记得要打开Safari浏览器的自动显示JSContent检查器,如下图:
    
    image

    当iOS模拟器跑起来后,Safari会自动弹出开发者工具,在控制台里面可以看到来自JavaScript的真挚问候:

    image

    刚才我们只是简单了通过原生调用了一段JS代码,但是如果Native在调JS方法时无法传参那也太low了,我们可以直接将要传递的参数格式化到字符串中,修改main.js文件如下:

    function put(name){
        console.log("Hello "+name);
    };
    put(%@);
    

    再封装一个OC方法如下:

    -(void)runJS_Hello:(NSString *)name{
        NSString * path = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"];
        NSData * jsData = [[NSData alloc]initWithContentsOfFile:path];
        NSString * jsCode = [[NSString alloc]initWithData:jsData encoding:NSUTF8StringEncoding];
        NSString * finiString = [NSString stringWithFormat:jsCode,name];
        [self.jsContext evaluateScript:finiString];
    }
    
    

    在viewDidLoad中进行调用,如下:

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.jsContext = [[JSContext alloc]init];
        [self runJS_Hello:@"'阿凡达'"];
    }
    

    运行再看Safari控制台的结果,编程了Hello 阿凡达~:

    image

    其实evaluateScript函数执行后会将JS代码的执行结果进行返回,是JSValue类型的对象,后面会再介绍。

    三、在JavaScript中调用Native方法

    有来无往非君子,同样也可以在原生中编写方法让JS来调用,示例如下:
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        void(^block)() = ^(){
            NSLog(@"Hello JavaScript");
        };
        self.jsContext = [[JSContext alloc]init];
        [self.jsContext setObject:block forKeyedSubscript:@"oc_hello"];
    }
    

    上面setObject:forKeyedSubscript:方法用来向JSContext环境的全局对象中添加属性,这里添加了一个函数属性,取名为oc_hello。这里JavaScriptCore会自动帮我们把一些数据类型进行转换,会将OC的函数转换为JS的函数,运行工程,在Safari的控制台中调用oc_hello函数,可以看到在Xcode控制台输出了对JavaScript的真挚问候,如下:

    image

    同样,如果声明的block是带参数的,JS在调用此OC方法时也需要传入参数,如果block有返回值,则在JS中也能获取到返回值,例如:

        BOOL (^block)(NSString *) = ^(NSString *name){
            NSLog(@"%@", [NSString stringWithFormat:@"Hello %@",name]);
            return YES;
        };
        self.jsContext = [[JSContext alloc]init];
        [self.jsContext setObject:block forKeyedSubscript:@"oc_hello"];
    

    原文转自:https://my.oschina.net/u/2340880/blog/856321

    相关文章

      网友评论

          本文标题:JavaScriptCore:OC和JS相互调用(不依赖于Web

          本文链接:https://www.haomeiwen.com/subject/gsftnhtx.html