JavaScriptCore提供了JavaScript和Objective-C桥接的Obj-C API。JavaScriptCore提供了让我们脱离UIWebView执行JavaScript脚本的能力,以及使用现代的Objective-C语法(例如Blocks和下标)在Objective-C和JavaScript之间无缝的传递值或者对象。借助JavaScriptCore,我们只需要很少的代码就可以完成OC与JS的交互通信,下面让我们一睹它的风采。同样,这篇文章会用JavaScriptCore有关API重写上一篇文章

一、JavaScriptCore概述

使用JavaScriptCore需要导入头文件"#import <JavaScriptCore/JavaScriptCore.h>",进入头文件我们会看到里面的类不多,只有下面5个:

#import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h"

JSContext: 代表JavaScript的运行环境,创建JSContext后,可以来执行JavaScript代码。

JSValue: 代表JavaScript实体,一个JSValue可以是JavaScript中的任意类型:字符串和数字;数组、对象和方法;甚至错误和特殊的 JavaScript 值诸如 null 和 undefined。任何JSContext的值都被包裹在一个JSValue对象中。

JSManagedValue: 本质上是一个JSValue,用来处理内存管理中的一些特殊情形,它能帮助OC引用技术和JS垃圾回收这两种内存管理机制之间进行正确的转换。

JSExport: 这是一个协议,可以用这个协议来将原生对象导出给JavaScript,这样原生对象的属性或方法就成为了JavaScript的属性或方法。

JSVirtualMachine: 代表一个对象空间,拥有自己的堆结构和垃圾回收机制,是运行JS代码的基础。大部分情况下不需要和它直接交互,除非要处理一些特殊的多线程或者内存管理问题。

二、JavaScriptCore深入

1. 方法调用

a. OC调用JS

//使用UIWebView执行js脚本的方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; //使用JSContext执行js脚本的方法
- (JSValue *)evaluateScript:(NSString *)script; //使用JSValuet执行js脚本的方法
- (JSValue *)callWithArguments:(NSArray *)arguments;

b. JS调用OC

有两种方式:block和JSExport协议

通过block可以直接讲某个功能的函数,注入给JSContext,使其调用,但要注意内存泄露

通过继承JSExport协议,可以将OC的方法,属性注入给JSContext,然后调用

2. 错误处理

当JavaScript运行时出现异常,会回调JSContext的exceptionHandler中设置的Block,然后在OC端进行错误处理

context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
NSLog(@"JS Error: %@", exception);
};

3. 内存管理

Objective-C的内存管理机制是引用计数,JavaScript的内存管理机制是垃圾回收。在大部分情况下,JavaScriptCore能做到在这两种内存管理机制之间无缝无错转换,但也有少数情况需要使用到JSManagedValue对象解决,后面会给出对应链接。

三、使用JavaScriptCore重写

沿用之前的示例,其他地方均无改动,只修改了两边交互的相关代码:

OC端:

1. 初始化JScontext

self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

2. 注入JS代码

__block typeof(self) weakSelf = self;
//JS调用OC方法列表
self.jsContext[@"showMobile"] = ^ {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf showMsg:@"我是下面的小红 手机号是:18870707070"];
});
}; self.jsContext[@"showName"] = ^ (NSString *name) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *info = [NSString stringWithFormat:@"你好 %@, 很高兴见到你",name];
[weakSelf showMsg:info];
});
}; void (^_showSendMsg) (NSString *num, NSString *msg) = ^ (NSString *num, NSString *msg) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *info = [NSString stringWithFormat:@"这是我的手机号: %@, %@ !!",num,msg];
[self showMsg:info];
});
}; [self.jsContext setObject:_showSendMsg forKeyedSubscript:@"showSendMsg"];

3. 执行JS端代码

//OC调用JS方法列表
- (IBAction)btnClick:(UIButton *)sender {
if (sender.tag == 123) {
//使用jsContext
[self.jsContext evaluateScript:@"alertMobile()"];
} if (sender.tag == 234) {
//使用webView
[self.webView stringByEvaluatingJavaScriptFromString:@"alertName('小红')"];
} if (sender.tag == 345) {
//使用jsValue
JSValue *jsValue = [self.jsContext objectForKeyedSubscript:@"alertSendMsg"];
[jsValue callWithArguments:@[@"18870707070",@"周末爬山真是件愉快的事情"]];
}
}

JS端:

//提供给OC调用JS的方法列表
function alertMobile() {
alert('我是上面的小黄 手机号是:13300001111')
} function alertName(msg) {
alert('你好 ' + msg + ', 我也很高兴见到你')
} function alertSendMsg(num,msg) {
alert('这是我的手机号:' + num + ',' + msg + '!!')
} //JS响应方法列表
function btnClick1() {
showMobile()
} function btnClick2() {
showName('xiaohuang')
} function btnClick3() {
showSendMsg('13300001111', 'Go Climbing This Weekend !!!')
}

了解过JavaScriptCore的原理及核心文件,核心类的作用,再过来上手重写,已经没有什么什么阻碍了,但是仍然有需要注意的地方。因为JavaScript是单线程的,在JS调用OC的代码都是在线程中执行的,所以和界面相关操作我们需要切换到主线程来刷新,其他流程和之前保持一致,学习这一部分参考了很多其他资料,文章后面给出了有关JavaScriptCore的介绍和实现原理解析的文章链接,有兴趣的同学可以传送之深入学习

四、后记

苹果的技术每年都会更新,在JavaScript这一块,每年也会出现新的惊喜,iOS8发布的时候,苹果又推出了WKWebView,对之前的UIWebView进行了一次脱胎换骨的重构(将UIWebView和UIWebViewDelegate重构成了14个类和3个协议),功能也更加完善和强大,稳定性和性能也明显提高。之前看到过一篇文章,详细介绍了WKWebView的相关API,对我了解这一模块提供了很大的帮助,后面我也系统的看完了整个WKWebView的API,受益匪浅,看的时候,我没有直接过去看这篇文章,而是先自己通读API然后对比这篇文章,查看理解方面的出入,同时也加深了印象,同学们也可以借鉴这种方式。下一篇文章,我们使用WKWebView的相关API来完成这个示例

戳这里:本文的DEMO地址欢迎star

参考资料(戳这里):

>  http://nshipster.cn/javascriptcore/

>  https://hjgitbook.gitbooks.io/ios/content/04-technical-research/04-javascriptcore-note.html

>  JavaScriptCore实现的原理解析系列

OC与JS交互之JavaScriptCore的更多相关文章

  1. OC和JS交互的三种方法

    看简书上说一共有六种OC和JS交互的方法,但是前三种原理都一致,都是通过检测.拦截Url地址实现互相调用的.剩下的react native等第三方框架原理不一样,也没有去研究,下边记录我使用的三种方法 ...

  2. iOS(UIWebView 和WKWebView)OC与JS交互 之二

    在iOS应用的开发过程中,我们经常会使用到WebView,当我们对WebView进行操作的时候,有时会需要进行源生的操作.那么我记下来就与大家分享一下OC与JS交互. 首先先说第一种方法,并没有牵扯O ...

  3. OC与JS交互之WebViewJavascriptBridge

    上一篇文章介绍了通过UIWebView实现了OC与JS交互的可能性及实现的原理,并且简单的实现了一个小的示例DEMO,当然也有一部分遗留问题,使用原生实现过程比较繁琐,代码难以维护.这篇文章主要介绍下 ...

  4. OC与JS交互之UIWebView

    随着H5的强大,hybrid app已经成为当前互联网的大方向,单纯的native app和web app在某些方面显得就很劣势.关于H5的发展史,这里有一篇文章推荐给大家,今天我们来学习最基础的基于 ...

  5. Mac Webview OC与JS交互实现

    1.首先,需要定义一个JS可识别的变量(如external)用于OC与JS交互 - (void)webView:(WebView *)sender didClearWindowObject:(WebS ...

  6. OC与JS交互前言

    OC与JS交互过程中,可能会需要使用本地image资源及html,css,js文件,这些资源应该如何被加载? 一.WebView加载HTML UIWebView提供了三个方法来加载html资源 1.  ...

  7. iOS(WKWebView)OC与JS交互 之三

      随着H5功能愈发的强大,没进行过混合开发的小伙们都不好意思说自己能够独立进行iOS的app开发,在iOS7操作系统下,常用的native,js交互框架有easy-js,WebViewJavascr ...

  8. OC与JS交互之WKWebView

    上一篇文章我们使用了JavaScriptCore框架重写了之前的示例,iOS8苹果偏爱HTML5,重构了UIWebVIew,给我们带来了WKWebView,使其性能.稳定性.功能大幅度提升,也更好的支 ...

  9. OC与JS交互

    https://www.jianshu.com/p/bb666b71e104 一.简述 目前原生与JS交互的方式有以下几种 JavaScriptCore WKWebView 拦截URL WebView ...

随机推荐

  1. OCP认证052考试最新考试题库和答案整理-33

    33.Where Is backup metadata stored for use by Recovery Manager (RMAN)? A) In the control file B) In ...

  2. Camel Games借助AWS在爆发式增长中提供优质游戏体验

    关于Camel Games Camel Games 成立于2009年,是中国首家得到google市场官方认证的顶尖开发公司.长期以来,Camel Games始终依靠于率先的技术背景,致力于成为国际一流 ...

  3. 剑指offer面试题1---赋值运算符函数

    题目描述:如下类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString{public:    CMyString(char* pData = NULL);    C ...

  4. awk常用用法

    一. 基本使用方法: awk '{pattern + action}' filenames #其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列 ...

  5. P3879 [TJOI2010]阅读理解 题解

    P3879 [TJOI2010]阅读理解 题解 题目描述 英语老师留了N篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过. 输 ...

  6. 网络传输层之TCP/UDP详解

    一.运输层协议概述 从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最低层. 运输层的任务就是负责主机中两个进程之间的通信,其数据传输的单 ...

  7. 读《3M 利率分析新框架》

    目录 读<3M 利率分析新框架> 前言 传统的利率研究框架 3M 利率研究新框架 Macro Monetary Macro Prudence 总结 参考文献 <3M 利率分析新框架& ...

  8. mysqldump 导出提示Couldn't execute SELECT COLUMN_NAME...

    mysqldump命令: 导出数据库:mysqldump -h ip -u root -p dbname > db.sql; 导出数据库中的某个表:mysqldump -h ip -u root ...

  9. php7 中?? 和 ?:的区别

    $b = $a?? $c ;相当于$b= isset($a)?$a:$c; $b = $a?: $c ;则是 $b = !empty($a) ? $a:$c;

  10. vue-tree 组织架构图/树形图自动生成(含添加、删除、修改)

    项目中用代码生成组织架构图  有新增,编辑,删除的功能            生成树形图的组件git-hub地址: https://github.com/tower1229/Vue-Tree-Char ...