iOS 开发与H5交互(JavaScriptCore框架的使用)
现在的iOS项目中嵌入了越来越多的Web界面,当然是为了方便,那么为了迎合这一趋势,作为iOS开发程序员,我们必须要了解怎么样用OC去和这些Web界面进行交互。这里介绍的是JavaScriptCore这个框架,他就是苹果为了解决这一问题而推出的框架。
JavaScriptCore的类说明
在做OC与H5的交互之前,我们需要先导入JavaScriptCore框架
#import <JavaScriptCore/JavaScriptCore.h>
然后我们进入到JavaScriptCore框架的JavaScriptCore.h,我们发现总共有如下几个类。
#if defined(__OBJC__) && JSC_OBJC_API_ENABLED #import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h" #endif
1. JSContext
JSContext 代表一个JavaScript的执行环境的一个实例。所有的JavaScript执行都是在上下文内。作为上下文,我们在很多情况下遇到过,比如CoreData,CoreGraphics等等,那么上下文对象到底是什么呢?你可以理解为是一个两者的连接桥梁,如图所示.

2.JSValue
JSValue的主要作用就是用来接收JSContext执行后的返回结果,当然了,JSValue可以是Js的任意类型。例如,JS中的变量,对象,以及函数。下面,我们举个例子来说明一下,例如我们现在需要从JSContext对象中接收到一个变量,我们可以如下所示。
首先在<script>标签中我们定义了一个字符串变量
<script type="text/javascript">
var myObject = "myObject";
</script>
然后,我们在OC的代码中如下表示,其中self.context代表着已经初始化完成的JSContext对象。
JSContext 对象的创建有两种方法
/*使用这个方法进行初始化 系统会自动创建一个JSVirtualMachine对象 然后 调用下面的方法 */
- (instancetype)init; /*!
JSVirtualMachine对象其实代表着一个JavaScript对象空间或者一组执行资源。初始化只需要init 就行了
*/
- (instancetype)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;
当然 如果你使用了WebView 你可以这样初始化一个JSContext对象
JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
有了JSContext,我们只需要在OC中写出下面的代码,就可以拿到我们在JS中定义的变量了
JSValue *value = self.context[@"myObject"];
//转换为OC的字符串
NSLog(@"%@",[value toString]);
3.JSManagedValue
JSManagedValue这个类其实到现在我还没有具体用到过.当时这里我也要根据API文档说明一下.JSManagedValue是JSValue的封装,用它可以解决JS和OC代码之间循环引用的问题,JSManagedValue最常用的用法就是安全的从内存堆区里面引用JSValue对象.如果JSValue存储在内存的堆区的方式是不正确的,很容易造成循环引用,然后导致JSContext对象不能正确的释放掉.
4.JSValueMachine
一个JSVirtualMachine对象其实代表着一个JavaScript对象空间或者一组执行资源。JSVirtualMachine支持线程安全锁,虚拟机,并发分配支持的JavaScript执行.也就说JSVirtualMachine用来管理整个JavaScript,当然了,这个类我也没有用到过.
5.JSExport
JSExport是一个协议,通过实现它可以完成把一个native对象暴漏给JS,当然了我们要指定native对象.比如我们指定native对象就是自身.如下所示.
self.context[@"native"] = self;
JavaScript 调取 OC的代码
那么我们怎么使用JavaScriptCore 进行JS与OC的交互呢,我们先来介绍JS调取OC的代码的方法。主要有两种方法:一种是很简单的直接使用Block,另一种是使用JSExport协议。
Block方式
block的方式比较简单,也是我比较推荐的一种,但是要注意防止循环引用问题。首先 我们说一下不带参数的函数调用,也就是我们不需要从网页那边有参数的传值。比如,页面跳转等等,代码如下:
HTML文件中的<body>标签中的按钮代码
<button type="button" onclick="buttonClick()">点击按钮返回上一个页面</button>
OC中在- (void)webViewDidFinishLoad:(UIWebView *)webView方法中对block块进行代码实现.
__weak typeof(self)weakSelf = self;
self.context[@"buttonClick"] = ^() {
[weakSelf.navigationController popViewControllerAnimated:YES];
};
这样当你点击Web页面上的按钮的时候,就会执行block中的代码。进行页面跳转。
接下来 我们看一下,通过页面的传值,我们把H5标签的之作为参数进行传值操作。并且调用OC的block进行打印。
HTML文件中的<body>标签中的代码
<body bgcolor="antiquewhite">
<!--<!–打开本地 或者网页–>-->
<!--<a href="news.html" target="_top">打开本地</a>-->
<!--<h1 align="center">标题一</h1>-->
<!--<h2 class="h2ID">标题2</h2>-->
<button type="button" onclick="buttonClick('你好','世界')">点击按钮返回上一个页面</button>
<script type="text/javascript">
function buttonClick(str1,str2) {
alert(str1 + "---" + str2);
}
</script>
</body>
OC调用这个block中的代码 有两种方法
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//第一种方法
// self.context[@"buttonClick"] = ^() {
// //获取该方法的所有参数
// NSArray *args = [JSContext currentArguments];
// for (JSValue *arg in args) {
// NSLog(@"%@",arg);
// }
//
// };
//第二种方法
self.context[@"buttonClick"] = ^(NSString *str1,NSString *str2) {
NSLog(@"%@ and %@",str1,str2);
};
}
点击按钮 可以看到 打印结果 你好 世界
JSExport 协议方式
通过实现JSExport协议方式进行OC与JS的交互,这里我只是简单的实现以下没有参数的函数调用.首先,我们在HTML文件中创建一个按钮用来调用OC中JSExport协议方法.
声明一个person类
.h
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h> @protocol webJsExport <JSExport> - (void) myButtonClick; @end @interface Person : NSObject<webJsExport> @end
.m #import "Person.h" @implementation Person - (void)myButtonClick {
NSLog(@"再来一次");
} @end
HTML
<button type="button" onclick="stu.myButtonClick()">JSExport没有参数</button>
调用
- (void)viewDidLoad {
[super viewDidLoad];
self.p = [[Person alloc] init];
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(, , self.view.frame.size.width, self.view.frame.size.height)];
self.webView.delegate = self;
NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
NSString *path = [[NSBundle mainBundle] pathForResource:@"Index" ofType:@"html"];
NSString *html = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[self.webView loadHTMLString:html baseURL:baseURL];
[self.view addSubview:self.webView];
// self.context = [[JSContext alloc] init];
// JSValue *value = self.context[@"myObject"];
// //转换为OC的字符串
// NSLog(@"%@",[value toString]);
// __weak typeof(self)weakSelf = self;
// self.context[@"buttonClick"] = ^() {
// [weakSelf.navigationController popViewControllerAnimated:YES];
// };
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//第一种方法
// self.context[@"buttonClick"] = ^() {
// //获取该方法的所有参数
// NSArray *args = [JSContext currentArguments];
// for (JSValue *arg in args) {
// NSLog(@"%@",arg);
// }
//
// };
//第二种方法
self.context[@"buttonClick"] = ^(NSString *str1,NSString *str2) {
NSLog(@"%@ and %@",str1,str2);
};
self.context[@"stu"] = self.p;
}
点击JSExport没有参数 会打印:在来一次
OC调用JavaScript函数
今天我们说一下如何使用JavaScriptCore让OC调用JavaScript函数,使用JavaScriptCore进行OC调用JavaScript函数是很容易进行传值操作的.首先我们需要在HTML文件创建爱你一个带有id的标签以及一个JavaScript函数.代码如下所示.
HTML代码
<b id="label">需要改变的标签</b>
<script type="text/javascript">
function labelAction(obj) { document.getElementById('label').innerHTML = obj; }
</script>
然后 就是OC中的代码了
下面就是实现方法,首先我们要先通过JSContext对象获取到JS中的对应函数并且使用JSValue对象进行接收.然后我们通过使用- (JSValue *)callWithArguments:(NSArray *)arguments;进行JS函数的调用,当然了这里的JS函数没有返回值,我也就没有做接收返回值的工作.
-(void)changeWebTxet{
JSValue *labelAction = self.context[@"labelAction"];
[labelAction callWithArguments:@[@"你好,JS世界!"]];
}
通过上面的介绍,我们可以看出来 使用JavaScriptCore 来进行OC与H5 的交互是很方便的,比以前通过WebView的一些方法交互方便多了。

iOS 开发与H5交互(JavaScriptCore框架的使用)的更多相关文章
- iOS开发系列—Objective-C之Foundation框架
概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NSObject,那么这个对象到底 ...
- iOS开发网络篇—使用ASI框架进行文件下载
iOS开发网络篇—使用ASI框架进行文件下载 说明:本文介绍iOS网络编程中经常用到的框架ASI,如何使用该框架进行文件的下载. 一.简单介绍 代码示例: #import "YYViewCo ...
- 浅谈 iOS 与 H5 的交互- JavaScriptCore 框架
前言 小的作为一个iOS程序猿,可能研究JavaScript以及H5相关的知识并不是为了真正的要去转行做这一方面,其实更多的为了要研究OC中的JavaScriptCore框架,JavaScriptCo ...
- iOS开发 UIWebView+JavaScript 交互总结
算是个人项目经验的,印象比较深的Web+JS交互的使用 iOS原生应用与Web页面元素交互方式有很多,JavaScriptCore.拦截协议.第三方框架WebViewJavaScriptBridge. ...
- ios和安卓H5交互桥接
ios交互 demo1(摘自网络) <!doctype html> <html> <head> <meta charset="UTF-8" ...
- iOS开发(0):框架QMUIKit的使用 | 使用第三方UI框架 | cocoapods的使用
对于移动APP来说,客户端(iOS或android)的界面开发是必不可少的工作.为了减轻界面开发的工作量,也为了提高开发的速度,选择一个良好的界面框架,是有意义的. iOS开源的界面框架有很多,比如c ...
- ios开发学习笔记040-autolayout 第三方框架Masonry
不管是是界面创建约束还是代码创建约束,苹果官方提供的方式都比较繁琐.所以出现了第三方框架. Masonry 在github地址如下: https://github.com/SnapKit/Masonr ...
- iOS原生与H5交互
一.WKWebView WKWebView 初始化时,有一个参数叫configuration,它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration ...
- iOS开发——JS网页交互——javaScript
JS中调用OC #import "ViewController.h" @interface ViewController () <UIWebViewDelegate> ...
随机推荐
- 【共享单车】—— React后台管理系统开发手记:城市管理和订单管理
前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录.最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star. ...
- hdu 4865 Peter's Hobby (隐马尔可夫模型 dp)
Peter's Hobby Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- chown将指定文件的拥有者改为指定的用户或组(转)
chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名或者组ID:文件是以空格分开的要改变权限的文件列表,支持通配符.系统管理员经常使用chown命令,在将文件拷贝 ...
- 訪问控制 protected, public, private 对照
OOP 3大特性:数据抽象,继承,动态绑定 3中訪问标号 protected, public, private 对照 用类进行数据抽象:用继承类继承基类的成员,实现继承.通过将基类对应函数声明为vir ...
- 【VBA】修改Excle的标题
打开Excle的时候,有时候不需要显示Miscrosoft Excle,如下图标记,想把标记内的内容替换为:管理系统 操作代码: Public Sub 修改标题() Application.Capti ...
- springMVC 前后台日期格式传值解决方式之一(共二) @DateTimeFormat的使用和配置
无意中发现对于时间字符串转Date类,根本不用自己去写转换类,spring mvc已经实现了该功能,还是基于注解的,轻松省事,使用 org.springframework.format.support ...
- c#实现记事本
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 详解zabbix安装部署(Server端篇) (转)
Linux下常用的系统监控软件有Nagios.Cacti.Zabbix.Monit等,这些开源的软件,可以帮助我们更好的管理机器,在第一时间内发现,并警告系统维护人员. 今天开始研究下Zabbix,使 ...
- Linux系统下如何监测磁盘的使用空间
不管是我们在安装软件还是监测软件的使用性能,我们都要随时掌握系统磁盘的使用情况. 使用df命令 df df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了 ...
- lua学习笔记(六)
(2012-04-12 23:32:35) 转载▼ 函数 定义 function mytest(a,b,c) <函数体> end mytest = function( ...