原文http://www.cnblogs.com/wanxudong/p/5581367.html http://www.cnblogs.com/wanxudong/p/5983706.html
前提:在iOS控制器中加载UIWebView,设置代理,遵守UIWebViewDelegate协议。
一、iOS调用JS方法
通过iOS调用JS代码实现起来比较方便直接调用UIWebView的方法- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
1.查询标签
// 查询标签
NSString *str = @"var word = document.getElementById('word');"
@"alert(word.innerHTML)";
[webView stringByEvaluatingJavaScriptFromString:str];
2.为网页添加标签:
NSString *str = @"var img = document.createElement('img');"
"img.src = 'icon5.jpg';"
"img.width = 300;"
"img.heigth = 100;"
"document.body.appendChild(img);";
[webView stringByEvaluatingJavaScriptFromString:str];
3.删除网页标签:
// 删除标签
NSString *str1 = @"var word = document.getElementById('word');"
@"word.remove();";
[webView stringByEvaluatingJavaScriptFromString:str1];
4.更改标签:
// 更改
NSString *str2 = @"var change = document.getElementsByClassName('change')[0];"
"change.innerHTML = 'hello';";
NSString *result = [webView stringByEvaluatingJavaScriptFromString:str2];
HTML端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iOS和H5交互</title>
</head>
<body>
<p id="word">6666666666</p>
<ul>
<li class="change">111111</li>
<li class="haha">222222</li>
<li>333333</li>
<li>444444</li>
</ul>
<input class="name" placeholder="请输入密码">
<button onclick="buttonClick()">提交信息</button>
<script type="text/javascript">
alert('这个一个弹框');
</script>
</body>
</html>
二、JS调用iOS方法:
1.第一种方法比较简单,通过字符串的比对。这种方式iOS端代码比较简单,网页加载完成后后台需要重新定义网页url,将移动端需要的参数拼接到url上返回,或者按照和后台约定好的字段来进行字符串比对以达到调用iOS方法的目的。下面贴代码。
oc代码:(需要实现webView的协议)
// 拦截协议头,调取系统摄像头
#pragma mark UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType: (UIWebViewNavigationType)navigationType
{
NSString *str = request.URL.absoluteString;
if ([str containsString:@"wxd://"]) {
[self getImage];
}
return YES;
}
- (void)getImage
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //调用相册
//实例化控制器
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
// 是否有图片选取框
picker.allowsEditing = YES;
[self presentViewController:picker animated:YES completion:nil];
}
}
HTML端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>在html中调用oc的方法</title>
</head>
<body>
<button onclick="getImage()">访问相册</button>
<script type="text/javascript">
function getImage(){
window.location.href = "wxd://getImage";
}
</script>
</body>
</html>
2.第二种方法,JS直接用oc方法名来调用oc方法,类似于安卓.addJavascriptInterface(new JsObject(), "Android")方法,头文件需要导入#import <JavaScriptCore/JavaScriptCore.h>。
首先创建一个继承自NSObject的类,在这里我命名为JSTestObjext,.h代码如下:
.m中实现协议方法,代码如下:
之后在加载webView的控制器中调用:
到此为止,oc代码就已经写完了,我们只需告诉JS端使用testobject类,就可以调oc的方法了。下面附上JS调用的代码:
到此公司里所使用的iOS与H5交互的方法就都写在这里了。
重点来了!
在这里推荐一个比较好的第三方库即:WebViewJavascriptBridge , 我没试过, 如果有需求,就试试,哈哈 ,懒加载啊
地址:https://github.com/marcuswestin/WebViewJavascriptBridge
通过使用该库可以轻松实现JS与原生交互。
//初始化WebViewJavascriptBridge方法
_bridge= [WebViewJavascriptBridge bridgeForWebView:self.BookWebView webViewDelegate:self handler:^(id data,WVJBResponseCallback responseCallback) {
}];
//原生与JS约定接口名为“testObjcCallback”,data是JS传递过来的信息,responseCallback来将信息传递给JS
[_bridge registerHandler:@"testObjcCallback" handler:^(id data,WVJBResponseCallback responseCallback) {
responseCallback("postInfomationToJS")
}];
UIWebView页面信息的离线缓存
推荐一个比较好的第三方库RNCachingURLProtocol ,只需要在AppDelegate中加入下面方法即可。
[NSURLProtocolregisterClass:[RNCachingURLProtocolclass]];
地址:https://github.com/rnapier/RNCachingURLProtocol
js 调 iOS , 另一种方法
一、原生框架<JavaScriptCore/JavaScriptCore>
(1)JavaScriptCore: 是一种JavaScript引擎,主要为webKit提供脚本处理能力,可以JS调用OC,也可以OC调用JS;
(2) JSContext: 代表了JS的执行环境,通过-evalueScript: 方法就可以执行-- JS代码;
(3) JSValue: 他封装了JS与OC中对应的类型,以及调用JS的API等;
(4) JSExport: 是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用;
二、交互方法
1.第一种:直接拦截H5页面中点击事件的URL,可以截取这个URL中的参数,进行拼接,然后跳转到自己指定的界面;
- #pragma mark ------------ 交互
- -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- {
- // 直接 截取后面的id
- NSString *str = request.URL.resourceSpecifier;
- NSLog(@"request.URL.resourceSpecifier = %@",request.URL.resourceSpecifier);
- NSString *strTwo = [NSString stringWithFormat:@"http:%@",str];
- NSRange range = [strTwo rangeOfString:@"newbieImg/"];
- if (range.location != NSNotFound) {
- NSArray *array = [strTwo componentsSeparatedByString:@"newbieImg/"];
- NSString *strId = array[1];
- NSLog(@"strId = %@", strId);
- CCCCCViewController *courseVC = [[CCCCCViewController alloc] init];
- courseVC.urlId = strTwo;
- [self.navigationController pushViewController:courseVC animated:YES];
- return NO;
- }
- return YES;
- }
2.需要与后台也就是写H5的人约定方法。但这里有两种方法,一种是JS调用OC, 一种是OC调用JS
(1)JS调用OC,并且传递参数
- //第一步 添加框架,引入头文件
- #import <JavaScriptCore/JavaScriptCore.h>
- @interface WebCenterViewController ()<UIWebViewDelegate>
- @property(nonatomic,strong) UIWebView *webView;
- //第二步 声明属性
- @property (nonatomic, strong) JSContext *context;
- @end
第三步,就需要知道后台指定的方法是什么了,比如
test1是一个无参数的方法,test2是一个有参数的方法,这时我们就可以在webView网页加载完毕的那个方法中写到:
- #pragma mark ------------ webView加载完毕
- -(void)webViewDidFinishLoad:(UIWebView *)webView
- { NSLog(@"网页加载完毕");
- //在网页加载完成后,获取每个参数
- //获取JS的运行环境
- _context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
- //JS调用无参数OC
- __weak WebCenterViewController *weakSelf = self;
- _context[@"test1"] = ^() {
- [weakSelf methond];
- };
- //JS调用有参数的OC
- _context[@"test2"] = ^() {
- //用数组接收传过来的多个参数
- NSArray *paramArray = [JSContext currentArguments];
- //然后取出相对应的值
- NSString *str1 = paramArray[0];
- NSString *str2 = paramArray[1];
- [weakSelf methondParam:str1 withStr:str2];
- };
- }
- //无参数的方法
- - (void)methond {
- NSLog(@"调用无参数的方法");
- }
- //有参数的方法
- - (void)methondParam:(NSString *)str1 withStr:(NSString *)str2 {
- NSLog(@"str1 = %@, str2 = %@", str1, str2);
- }
注意::::调用的方法名test1,test2,一定要和html中的保持一致!!!!!!