OC与JS交互之JavaScriptCore
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
OC与JS交互之JavaScriptCore的更多相关文章
- OC和JS交互的三种方法
看简书上说一共有六种OC和JS交互的方法,但是前三种原理都一致,都是通过检测.拦截Url地址实现互相调用的.剩下的react native等第三方框架原理不一样,也没有去研究,下边记录我使用的三种方法 ...
- iOS(UIWebView 和WKWebView)OC与JS交互 之二
在iOS应用的开发过程中,我们经常会使用到WebView,当我们对WebView进行操作的时候,有时会需要进行源生的操作.那么我记下来就与大家分享一下OC与JS交互. 首先先说第一种方法,并没有牵扯O ...
- OC与JS交互之WebViewJavascriptBridge
上一篇文章介绍了通过UIWebView实现了OC与JS交互的可能性及实现的原理,并且简单的实现了一个小的示例DEMO,当然也有一部分遗留问题,使用原生实现过程比较繁琐,代码难以维护.这篇文章主要介绍下 ...
- OC与JS交互之UIWebView
随着H5的强大,hybrid app已经成为当前互联网的大方向,单纯的native app和web app在某些方面显得就很劣势.关于H5的发展史,这里有一篇文章推荐给大家,今天我们来学习最基础的基于 ...
- Mac Webview OC与JS交互实现
1.首先,需要定义一个JS可识别的变量(如external)用于OC与JS交互 - (void)webView:(WebView *)sender didClearWindowObject:(WebS ...
- OC与JS交互前言
OC与JS交互过程中,可能会需要使用本地image资源及html,css,js文件,这些资源应该如何被加载? 一.WebView加载HTML UIWebView提供了三个方法来加载html资源 1. ...
- iOS(WKWebView)OC与JS交互 之三
随着H5功能愈发的强大,没进行过混合开发的小伙们都不好意思说自己能够独立进行iOS的app开发,在iOS7操作系统下,常用的native,js交互框架有easy-js,WebViewJavascr ...
- OC与JS交互之WKWebView
上一篇文章我们使用了JavaScriptCore框架重写了之前的示例,iOS8苹果偏爱HTML5,重构了UIWebVIew,给我们带来了WKWebView,使其性能.稳定性.功能大幅度提升,也更好的支 ...
- OC与JS交互
https://www.jianshu.com/p/bb666b71e104 一.简述 目前原生与JS交互的方式有以下几种 JavaScriptCore WKWebView 拦截URL WebView ...
随机推荐
- 解决$ git clone fatal: Authentication failed
今天在使用git clone克隆项目的时候报如下错误: $ git clone XXXXXX Cloning into 'XXXX'... fatal: Authentication failed f ...
- 五、Centos linux系统优化-实战
一.linux用户名和密码远程登陆的修改: windows默认的远程端口和管理员:user:administrator prot:3389在管理--->本地用户和组 进行权限设置或者修 ...
- “全栈2019”Java第六十一章:如何实现接口?
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- CF223C【Partial Sums】(组合数学+乱搞)
题面 传送门 题解 orz zzk 考虑这东西的组合意义 (图片来自zzk) \(a_i\)这个元素对\(k\)阶前缀和的第\(j\)个元素\(s_{k,j}\)的贡献就等于从\((0,i)\)走到\ ...
- bzoj 3669: [Noi2014]魔法森林(并查集+LCT)
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
- PHP删除一个目录下的所有文件,不删除文件夹
/*删除指定目录下的文件,不删除目录文件夹*/ function delFile($dirName){ if(file_exists($dirName) && $handle=open ...
- classnofoundexception:org.springframework.ui.freemarker.FreeMarkerConfigurationFactory
这个是在整合freemarker的时候出现的问题,在添加依赖spring-context-support.jar之后就好了 但是我在搭建框架的时候出现的问题是明明添加了这个依赖,但是出现一个问题 出现 ...
- word的xml文件中空白页和换页
■ word中分页符(插入空白页): <w:r> <w:rPr> <w:rFonts w:as ...
- 初学C#,用vs去开始hello world!
小弟初学c#,刚刚学会用vs来编写经典的hello,world程序,记录,并且分享给大家. 1. 用vs新建一个c#控制台程序: a. 首先打开vs,如下图所示,点击[新建项目]
- linux使用rsync、inotify-tools实现多台服务器文件实时同步
需求:将本地192.168.1.10上的/data/wwwroot目录同步到 1.来源服务器上安装rsync.inotify-tools yum -y install rsync yum -y ins ...