iOS---javascript直接调用oc代码而非通过改变url回调方式
2015-12-09 15:57
756 查看
转载自:http://blog.csdn.net/j_akill/article/details/44463301
之前一个ios项目中,需要通过UIWebview来打开一个静态页面,并在静态页面中
调用相关object-c代码。
关于如何使用javascript调用object-c中的函数和方法,我搜索了好久
网上所有的方法,基本都指明了一个方向,那就是在UIWebview中载入的js代码中
通过改变document.locations=“”,然后回调UIWebview的
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
函数,在上面这个函数中,通过截取NSURLRequest解析js中传递过来的参数,再根据参数
来选择早已定义好的方法。
有没有别的方法呢? 我找了几个月,没找到!但是有一个转机。
我偶然知道了 javascriptCore.framework 这个库
于是事情有了转机。
二、在js中直接调用oc的方法
废话不多说,现在看看如何在UIWebView的javascript中调用oc的方法
首先在建立一个UIWebView,代码如下:
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
//
// webview.m
// login
//
// Created by wangdan on 15-3-19.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import "webview.h"
#import <JavaScriptCore/JavaScriptCore.h>
@implementation webview
-(id)initWithFrame:(CGRect)frame
{
self=[super initWithFrame:frame];
if( self ){
self.webview=[[UIWebView alloc]initWithFrame:CGRectMake(0, 310, self.bounds.size.width, 300)];
self.webview.backgroundColor=[UIColor lightGrayColor];
NSString *htmlPath=[[NSBundle mainBundle] resourcePath];
htmlPath=[htmlPath stringByAppendingPathComponent:@"html/index.html"];
NSURL *localURL=[[NSURL alloc]initFileURLWithPath:htmlPath];
[self.webview loadRequest:[NSURLRequest requestWithURL:localURL]];
[self addSubview:self.webview];
JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"log"] = ^() {
NSLog(@"+++++++Begin Log+++++++");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"this: %@",this);
NSLog(@"-------End Log-------");
};
// [context evaluateScript:@"log('ider', [7, 21], { hello:'world', js:100 });"];
}
return self;
}
@end
(1)在上述代码中,使用javascriptCore.framework,首先使用UIWebview加载一个静态网页,并
使用
JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
获取该UIWebview的javascript执行环境。
(2)在该javascript执行环境中,定义一个js函数,注意关键点来了
这个函数的执行体完全是 objective-c代码写的,也就是下面:
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
context[@"jakilllog"] = ^() {
NSLog(@"Begin Log");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"-------End Log-------");
};
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
(3)试想一下,在定义的webview中,如果使用js执行log这个函数,那么会不会调用上面oc中block段代码呢,答案是肯定的!
下面看看UIWebView 中所加载的 html及其js代码是如何写的
(4)index.html代码
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
<!--// Created by wangdan on 15-3-19.-->
<!--// Copyright (c) 2014年 wangdan. All rights reserved.-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<script type="text/javascript" src="index.js"></script>
</head>
<button id="hallo" onclick="buttonClick()"> 点击button</button>
</body>
</html>
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
上面html定义了一个button,然后引用index.js,点击button的响应函数为buttonClick()
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
该函数在index.js中定义,如下
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
function buttonClick()
{
jakilllog("hello world");
}
意思是点击这个button,就调用jakilllog()函数,jakilllog()函数显然是我们在oc中实现的一个block段,
就是上述绿色部分的block段。
点击button会执行么?答案是肯定的。
下面上图
![](https://oscdn.geek-share.com/Uploads/Images/Content/201507/ca34bce17c5911d8a32044936e37ec78)
下图是执行的结果
![](https://oscdn.geek-share.com/Uploads/Images/Content/201507/9b0ffbf96d9f4cfe7eeaee2224809e25)
点击html中的button,能够执行oc中的代码
说明直接从js调用oc的意图达到。
最近有很多朋友问我索要demo那么我把demo的地址上传到csdn
大家下载下来就很方便了。
demo地址
之前一个ios项目中,需要通过UIWebview来打开一个静态页面,并在静态页面中
调用相关object-c代码。
一、以前使用js调用object-c的方法
关于如何使用javascript调用object-c中的函数和方法,我搜索了好久网上所有的方法,基本都指明了一个方向,那就是在UIWebview中载入的js代码中
通过改变document.locations=“”,然后回调UIWebview的
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
函数,在上面这个函数中,通过截取NSURLRequest解析js中传递过来的参数,再根据参数
来选择早已定义好的方法。
有没有别的方法呢? 我找了几个月,没找到!但是有一个转机。
我偶然知道了 javascriptCore.framework 这个库
于是事情有了转机。
二、在js中直接调用oc的方法
废话不多说,现在看看如何在UIWebView的javascript中调用oc的方法
首先在建立一个UIWebView,代码如下:
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
//
// webview.m
// login
//
// Created by wangdan on 15-3-19.
// Copyright (c) 2015年 wangdan. All rights reserved.
//
#import "webview.h"
#import <JavaScriptCore/JavaScriptCore.h>
@implementation webview
-(id)initWithFrame:(CGRect)frame
{
self=[super initWithFrame:frame];
if( self ){
self.webview=[[UIWebView alloc]initWithFrame:CGRectMake(0, 310, self.bounds.size.width, 300)];
self.webview.backgroundColor=[UIColor lightGrayColor];
NSString *htmlPath=[[NSBundle mainBundle] resourcePath];
htmlPath=[htmlPath stringByAppendingPathComponent:@"html/index.html"];
NSURL *localURL=[[NSURL alloc]initFileURLWithPath:htmlPath];
[self.webview loadRequest:[NSURLRequest requestWithURL:localURL]];
[self addSubview:self.webview];
JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"log"] = ^() {
NSLog(@"+++++++Begin Log+++++++");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"this: %@",this);
NSLog(@"-------End Log-------");
};
// [context evaluateScript:@"log('ider', [7, 21], { hello:'world', js:100 });"];
}
return self;
}
@end
(1)在上述代码中,使用javascriptCore.framework,首先使用UIWebview加载一个静态网页,并
使用
JSContext *context = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
获取该UIWebview的javascript执行环境。
(2)在该javascript执行环境中,定义一个js函数,注意关键点来了
这个函数的执行体完全是 objective-c代码写的,也就是下面:
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
context[@"jakilllog"] = ^() {
NSLog(@"Begin Log");
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSLog(@"%@", jsVal);
}
JSValue *this = [JSContext currentThis];
NSLog(@"-------End Log-------");
};
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
[objc] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
(3)试想一下,在定义的webview中,如果使用js执行log这个函数,那么会不会调用上面oc中block段代码呢,答案是肯定的!
下面看看UIWebView 中所加载的 html及其js代码是如何写的
(4)index.html代码
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
<!--// Created by wangdan on 15-3-19.-->
<!--// Copyright (c) 2014年 wangdan. All rights reserved.-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<script type="text/javascript" src="index.js"></script>
</head>
<button id="hallo" onclick="buttonClick()"> 点击button</button>
</body>
</html>
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
上面html定义了一个button,然后引用index.js,点击button的响应函数为buttonClick()
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
该函数在index.js中定义,如下
[html] view
plaincopy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
function buttonClick()
{
jakilllog("hello world");
}
意思是点击这个button,就调用jakilllog()函数,jakilllog()函数显然是我们在oc中实现的一个block段,
就是上述绿色部分的block段。
点击button会执行么?答案是肯定的。
下面上图
下图是执行的结果
点击html中的button,能够执行oc中的代码
说明直接从js调用oc的意图达到。
最近有很多朋友问我索要demo那么我把demo的地址上传到csdn
大家下载下来就很方便了。
demo地址
相关文章推荐
- iOS-Foundation框架(NSDate.h解读)
- iOS---网页中调用JS与JS注入
- IOS 后台执行
- iOS编程笔记1
- iOS项目集成ShareSDK实现第三方登录、分享、关注等功能。
- iOS屏幕适配知识
- iOS开发中FMDB的使用
- ios lua 增量更新,更新内部代码
- iOS 开发 消除导航栏黑线
- ios9Tips
- iOS 伪亮度调节/控制
- 【iOS】tableView:cellForRowAtIndexPath: 方法未调用
- CABasicAnimation精讲
- ios基本框架
- iOS 图片相关
- 关于IOS9的本地通知方法
- nagios监控cfg模块
- 监控cacti/nagios/zabbix (二)nagios
- [Cordova] Plugin里使用iOS Framework
- iOS 关联对象的使用