UIWebView的应用和其中的JS与OC间传值
现在有很多的应用已经采用了WebView和html语言结合的开发模式。html5一直很火因为一份代码可以在多个平台上运用啊,效果各不相同都很美观,也越来越有一些公司直接招后台程序员和html5程序员,做完的产品再安卓也能用iOS也能用,不用再招双份的工程师了。应用程序一进去就全是UIWebView,里面发个请求到自己用html5做的页面,这就是一个应用!当然今天的主要不是说html5,是说html语言中JS代码和OC代码之间的传值。
先举例一个简单的用法:
我在模仿网易彩票做到设置页面的 常见问题板块时,扒到的素材是一个html网页格式的
也就是说只要设置好了这些按钮点进去都是一个页面,只是每一个按钮都绑定了一个 html.id的属性 ,会html语言的都知道 有了id属性可以直接跳到页面的该位置。
如图点击进入后 会跳到这个界面,点击了如何充值按钮,页面会自动跳到如何充值顶着边。如果点击了如何购彩,页面也会自动跳到自动购彩顶着边。当然了如果倒数第二个倒数第一个估计就跳不上去了,因为下面已经见底了拖上去会弹回来的所以跳不上去了,这点和C#开发的时候是一样的。
此功能的做法:
// 建立webView
UIWebView *web = (UIWebView *)self.view; // 发送请求前需要请求和请求的链接
NSURL *url = [[NSBundle mainBundle] URLForResource:_html.html withExtension:nil];
NSURLRequest *request = [NSURLRequest requestWithURL:url]; // $$$$$
[web loadRequest:request];
web.delegate = self;
首先要有webView啊,我是手码创建的
上面html是我的模型,html模型里html是一个链接打开本地的一个web文件。你也可以自己找好链接做一个plist再做一个模型
发送请求,接收数据之后,用webView加载数据
然后再给自己的webView设置代理为自己,然后遵守协议UIWebViewDelegate,就可以实现代理方法了
- (void)webViewDidFinishLoad:(UIWebView *)webView
这个方法在页面加载完成后会调用,在这个方法中来做些js的操作。
想做js的操作,一般都是先把你想要的js代码拼接接出一个字符串,再用这个方法传入这个字符串完成操作
// 拼接一个脚本语言中的 自动定位代码
NSString *javascript = [NSString stringWithFormat:@"window.location.href = '#%@'",_html.ID]; // 加载完成后执行这个代码
[webView stringByEvaluatingJavaScriptFromString:javascript];
里面的html.ID是字符串中的一个id属性,控制往哪跳的。
这样核心功能就完成了。
下面再说一个高级点的用法
这是我在模仿网易新闻时做到的新闻详情界面,
如图点击其中的这个库里上篮这一行,进入的新闻详情页面是用html做的,扒到的数据就是这样了,但是数据只有乱七八糟的一大串字符,需要自己排版的,特别是图文混排有点麻烦。。这里今天就不说了,今天主要说下JS和OC间如何传值,关于图文混排 过几天有时间了再详细写一篇。(欢迎关注我评论我)
进去之后是一个新闻详情页面,里面是有图片的,有的图片很好看我就想保存,但是问题来了,webView里面的图片都是<div><img height= src=></img>什么什么的不是UI控件按钮可以绑定事件,imgView至少也可以监听手势点击,这个是网页啊,如何做到点击图片下面弹出一个shit问你保不保存?
这就用到JS代码和OC代码见的传值了,
一般大概思路是这边发请求,那边把请求拦下来,再扒出请求url里的字符串,再各种截取得到有用的数据
核心思路如下,从一半开始截的
NSString *onload = @"this.onclick = function() {"
" window.location.href = 'sx:src=' +this.src;"
"};";
[imgHtml appendFormat:@"<img onload=\"%@\" width=\"%f\" height=\"%f\" src=\"%@\">",onload,width,height,detailImgModel.src];
// 结束标记
[imgHtml appendString:@"</div>"];
// 替换标记
[body replaceOccurrencesOfString:detailImgModel.ref withString:imgHtml options:NSCaseInsensitiveSearch range:NSMakeRange(0, body.length)];
}
return body;
其中onload就是加载完毕后才用,然后onclick是JS里的点击触发,window.location.href 是跳往哪里,后面是一个url 里面的协议头是sx:src= 后面是自己图片的src。 SX是我自己的符号。
就相当于我自己乱写了一个协议头sx://www.啥 ,有了协议头这就是一个跳转网页的请求 但是要注意的是,我把// 和www啥的省略了 但是前面这个sx:src=不能再省略了,如果再省略就不是协议头了,苹果就会自己给你加一个他的协议头很长很乱 后面接不住了。
然后写这个方法 ,webView的代理方法
这个方法是在即将发送请求时会被调用,返回值是一个BOOL类型,说白了就是让你控制什么请求允许发出去,什么请求拦下。
NSString *url = request.URL.absoluteString;
NSRange range = [url rangeOfString:@"sx:src="];
if (range.location != NSNotFound) {
NSInteger begin = range.location + range.length;
NSString *src = [url substringFromIndex:begin];
[self savePictureToAlbum:src];
return NO;
}
return YES;
先取出这个请求的全url再算出sx:src=这个字符串的范围,如果是别的真正的请求,是取不到值的,就是NSNotFound,这是允许发出去的
如果取到range了 那就是我写的这个请求,就从这个范围往后的字符串全截取下来,这就是html代码里那个图片的地址了this.src。
然后有了url链接就可以保存到相册了。
保存到相册那个方法里,有两种选择一种是重新下载保存,一种是从缓存中取,这种比较省流量。
NSURLCache *cache =[NSURLCache sharedURLCache];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:src]];
NSData *imgData = [cache cachedResponseForRequest:request].data;
UIImage *image = [UIImage imageWithData:imgData];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
应该都能看懂的吧,大意就是通过这个url找到我上次请求中用这个url弄到的响应数据再转化成图片保存入相册。
到此就完成了JS与OC间的传值
当然如果只有这样那还远远不够
这里是只有一个保存图片的方法,如果以后又有很多需要拦截的方法,打电话或者发短信等各种各样的方法,都要一一判断就太麻烦了。
聪明的做法是把 需要调用的方法名 和 要传的参数 都通通写在url里让我拦
比如sx:call:&10086
然后我通过字符串的切割就可以 得到一个方法名 call:和一个参数10086
就可以调用- (void)call:(NSString *)phoneNumber 这个方法了。
NSRange range = [url rangeOfString:@"sx:"];
if (range.location != NSNotFound) {
NSUInteger loc = range.location + range.length;
NSString *path = [url substringFromIndex:loc];
// 获得方法和参数
NSArray *methodNameAndParam = [path componentsSeparatedByString:@"&"];
// 方法名
NSString *methodName = [methodNameAndParam firstObject];
// 调用方法
SEL selector = NSSelectorFromString(methodName);
if ([self respondsToSelector:selector]) { // 判断方法的目的: 防止因为方法不存在而报错
这一串代码写的很清楚了,获得方法名和参数,把字符串转化成SEL 然后下面就可以这么写了
调用打电话方法 call 传的值是 10086
如果遇到了有的方法需要传多个值。那就该这么写
sx:sendMsg:body:&18686652446&loveyou
通过切割可以得到方法名是 sendMsg:body: 要传的参数用&切开 就是这个(componentsSeparatedByString:@"&")得到两个参数电话号码和信息内容
然后就可以调用这个方法了
这里我要说一下
如果要传入3个4个好多个参数,要用到一个第三方框架
// Copyright (c) 2015年 shangxianDante. All rights reserved.
// #import <Foundation/Foundation.h> @interface NSObject (Extension)
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects; @end
// Copyright (c) 2015年 shangxianDante. All rights reserved.
// #import "NSObject+Extension.h" @implementation NSObject (Extension)
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects {
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
if (signature) {
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:selector];
for(int i = 0; i < [objects count]; i++){
id object = [objects objectAtIndex:i];
[invocation setArgument:&object atIndex: (i + 2)];
}
[invocation invoke];
if (signature.methodReturnLength) {
id anObject;
[invocation getReturnValue:&anObject];
return anObject;
} else {
return nil;
}
} else {
return nil;
}
}
@end
然后就可以用这个方法啦
最后我想再说个简单的小技巧
就是因为现在html5很火,就是一份代码在电脑是一个界面在手机又是一个界面,很漂亮。有时候可以直接搬过来用但是最下面的页脚(也许是广告)又不想要,就可以直接截了,把人家网站搬过来再把人家的页脚截了,有意思吧
- (void)viewDidLoad {
[super viewDidLoad]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://v3.bootcss.com/"]];
self.webView.delegate = self;
[self.webView loadRequest:request];
} #pragma mark - ******************** web代理方法
/**
* 网页加载完毕后调用
*/
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *js = @"document.getElementsByTagName('footer')[0].remove();";
[webView stringByEvaluatingJavaScriptFromString:js];
当然首先你肯定要用浏览器的开发者工具找到页脚这部分板块的名字叫footer啊,然后截了。
(董铂然博客所有文章都是原创欢迎评论和关注)
UIWebView的应用和其中的JS与OC间传值的更多相关文章
- 【转】使用JavaScriptCore在JS和OC间通信
http://www.cocoachina.com/ios/20160623/16796.html iOS 开发中,我们时不时的需要加载一些 Web 页面,一些需求使用 Web 页面来实现可以更可控, ...
- JS和OC间的通信(使用JavaScriptCore)
JavaScriptCore 时代的通讯 iOS 7 开始,苹果提供了一个叫作 JavaScriptCore 的框架,使用 JavaScriptCore 框架可以实现 OC 和 JS 的互相调用,而不 ...
- iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge
WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000+star.我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以 ...
- iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用,这一篇来介绍一下WKWebView 又是如何通过WebViewJavascr ...
- [iOS Hybrid实践:UIWebView中Html中用JS调用OC方法,OC执行JS代码]
原理: 1.JS调用OC 每次webview执行跳转时都会被iOS给拦截,执行下面函数获得系统允许. 因此可以根据跳转信息转给系统,执行相应功能,比如打开相册等. // 网页中的每一个请求都会被触发 ...
- UIWebView中Html中用JS调用OC方法及OC执行JS代码
HTML代码: <html> <head> <title>HTML中用JS调用OC方法</title> <meta http-equiv=&quo ...
- 史上最全的 UIWebview 的 JS 与 OC 交互
来源:伯乐在线 - 键盘风筝 链接:http://ios.jobbole.com/89330/ 点击 → 申请加入伯乐在线专栏作者 其实一直想给大家整理一下JS与OC的交互,但是没有合适的机会,今天借 ...
- iOS下JS与OC互相调用(一)--UIWebView 拦截URL
最近准备把之前用UIWebView实现的JS与原生相互调用功能,用WKWebView来替换.顺便搜索整理了一下JS 与OC 交互的方式,非常之多啊.目前我已知的JS 与 OC 交互的处理方式: * 1 ...
- UIWebView中JS与OC交互 WebViewJavascriptBridge的使用
一.综述 现在很多的应用都会在多种平台上发布,所以很多程序猿们都开始使用Hybrid App的设计模式.就是在app上嵌入网页,只要写一份网页代码,就可以跑在不同的系统上.在iOS中,app多是通过W ...
随机推荐
- NODE.JS学习的常见误区及四大名著
NODE.JS学习的常见误区及四大名著 前段时间由于不满于社区里很多人对于NODE.JS的种种误解而写了一篇文章名为: NODE.JS之我见:http://www.cnblogs.com/pugang ...
- Windows Azure Web Site (12) Azure Web Site配置文件
<Windows Azure Platform 系列文章目录> 本文将介绍如何在Azure Web Site里配置连接字符串. 本文分为以下几个步骤: 1.在本地ASP.NET项目使用W ...
- c# 游戏策划配置工具
该工具是提供策划配置excel数据,导出到mysql数据库,以及生成xml文件,和对应的xml解析实体类 实现了程序 excel 列名 ID =P 表示ID这列是唯一字段 =S=300 表示这列类型是 ...
- 使用James搭建一个自己的邮箱服务器
---第一天开发--- 下载Apache James 3.0邮箱服务器,解压到响应的目录 可以看到目录结构: H:\code\JavaCode\James\apache-james-3.0-beta4 ...
- 【视频处理】YUV格式说明
YUV,是一种颜色编码方法,Y表示明亮度(Luminance.Luma),U和V则是色度.浓度(Chrominance.Chroma). YUV,Y`UV,YCbCr,YPbPr等都可以称为YUV,彼 ...
- TCP 与 UDP
TCP Transmission Control Protocol,传输控制协议,传输层通信协议. 采用“带重传的肯定确认”(Positive Acknowledge with Retransmiss ...
- C# WebClient 使用http免费代理。
static void Main(string[] args) { WebClient client = new WebClient(); client.Encoding = Encoding.Get ...
- IIS 7.5 应用程序池预热模块组件
预热组件下载地址:下载地址 IIS预热模块配置界面插件:下载地址 Warm Up设定方式: (1) 应用程序池层级:只要有需要的应用程序池的Start Mode设定AlwaysRunning就可以 ( ...
- maven安装与配置(第一天学习笔记)
Maven下载:http://maven.apache.org/ 1.首先要确保JDK已经安装与配置(注意:用的是apache-maven-3.3.3的JDK1.6不行,我用的是JDK1.8) 2.把 ...
- ios 根据文字数量计算UILabel高度(已修改)
由于留言的朋友给出了更好的方法,所以下面的代码都是它留言中给出的,优于我前面计算Lable高度方法,这个可以说非常的准,是IOS自带的计算UILABEL高度的方式. 一.实现代码 // 创建label ...