一:前言
有于本人对html,web网页制作比较感兴趣,所以身为ios程序员的我不务正业的看起了js,css,html,jq等的相关信息,发现了一片新大陆啊,可惜本人学业不精只能学到一点皮毛。
由于最近web相关的都比较火,所以也开始研究了下ios与js的相关的一些通信交互,但是研究的比较浅,写写微博,这样自己就也能记得住。
我的简易的demo: https://github.com/taosiyu/TSYJavaScriptCoreDemo 请大家点个星星啊
二:关于javaScriptCore
iOS7以后苹果加入了JavaScriptCore.framework的框架。把 WebKit 的 JavaScript 引擎用 Objective-C 封装。让Objective-C和JavaScript代码的交互变得简单方便。至于ios7之前的方法框架由于现在ios7之前的机器较少而且利用截取方式调用感觉不怎么高大上,所以直接忽略,如果硬要了解请查看楼底的分享链接。
JSContext和JSValue
JSVirtualMachine为JavaScript的运行提供了底层资源,JSContext就为其提供着运行环境,通过- (JSValue *)evaluateScript:(NSString *)script;方法就可以执行一段JavaScript脚本,并且如果其中有方法、变量等信息都会被存储在其中以便在需要的时候使用。而JSContext的创建都是基于JSVirtualMachine:- (id)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;,如果是使用- (id)init;进行初始化,那么在其内部会自动创建一个新的JSVirtualMachine对象然后调用前边的初始化方法。
JSValue则可以说是JavaScript和Object-C之间互换的桥梁,它提供了多种方法可以方便地把JavaScript数据类型转换成Objective-C,或者是转换过去。
JSContext 可以通过[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];来获取js环境
当然在使用框架之前首先要导入头文件
#import
然后再载入html页面
在页面加载完成之后
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//获取js的环境,在这里获取是为了避免页面没有加载完成导致oc调不到 js的方法
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 打印异常,由于JS的异常信息是不会在OC中被直接打印的,所以我们在这里添加打印异常信息,
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
}
}
JS --------调用------>OC
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// 以 html title 设置 导航栏 title
self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
// Undocumented access to UIWebView's JSContext
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 打印异常
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
};
// 以 JSExport 协议关联 native 的方法
self.context[@"app"] = self;
// 以 block 形式关联 JavaScript function
self.context[@"log"] =
^(NSString *str)
{
NSLog(@"%@", str);
};
self.context[@"wowowowow"] =
^(NSString *str)
{
NSLog(@"============================>>>>>>>>>>>>>%@",str);
};
// 以 block 形式关联 JavaScript function
self.context[@"alert"] =
^(NSString *str)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"msg from js" message:str delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[alert show];
};
__block typeof(self) weakSelf = self;
self.context[@"addSubView"] =
^(NSString *viewname)
{
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 500, weakSelf.view.frame.size.width, 100)];
view.backgroundColor = [UIColor redColor];
[weakSelf.view addSubview:view];
};
//多参数
self.context[@"mutiParams"] =
^(NSString *a,NSString *b,NSString *c)
{
NSLog(@"%@ %@ %@",a,b,c);
};
[self.context evaluateScript:@"var squareFunc = function(value) { return value * 2 }"];
JSValue *S = [self.context evaluateScript:@"squareFunc(10)"];
NSLog(@"tonumber = %@",S.toNumber);
}
主要是看看js调用oc的方法比以前用截取的方法方便很多,也更符合mvc的思想,让js和oc的关系更紧密.
其它的请自行查看代码,说一堆废话不如直接上代码(其实是楼主懒)。