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 ...
随机推荐
- java类加载器-Tomcat类加载器
在上文中,已经介绍了系统类加载器以及类加载器的相关机制,还自定制类加载器的方式.接下来就以tomcat6为例看看tomat是如何使用自定制类加载器的.(本介绍是基于tomcat6.0.41,不同版本可 ...
- C#密封类
密封类 密封类使用sealed修饰符声明. 密封类中不可能有抽象方法[因为:抽象方法必须在抽象类中,而抽象类不能是密封的或者是静态的,也就是说abstract 和sealed不能同时修饰一个类] ...
- STL : map函数的运用 --- hdu 4941 : Magical Forest
Magical Forest Time Limit: 24000/12000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- IIS 架构解析
我们在使用ASP.NET平台做web开发的时候,经常会接触到IIS(Internet Information Services 互联网信息服务).这篇文章主要来介绍IIS7.0+的架构.IIS的安全脆 ...
- 使用html和css的一些经验
1.注释须知:html中注释不能这样写: <div></div><!--------这是错误写法-------> <div></div>&l ...
- Qt的tablewidget行列头自适应宽度
Qt构造一个TableWidget后,窗口最大化后,列头默认不能自适应宽度,研究了一下,Qt提供了两种方式来处理这个问题,如下: 1. 使用horizontalHeader()->setRe ...
- 编写高性能SQL
前言:系统优化中一个很重要的方面就是SQL语句的优化.对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可达到上百倍,可见对于一个系统不是简单的能实现其功能就可以了,而是要写出高质量的SQL语 ...
- ASP.NET页面中去除VIEWSTATE视
保存页的所有视图状态信息和控件状态信息. 源码:http://www.jinhusns.com/Products/Download/?type=xcj 作者在早期参与的项目中曾遇到这样的需求:基于SE ...
- MVC中几种常用ActionResult
一.定义 MVC中ActionResult是Action的返回结果.ActionResult 有多个派生类,每个子类功能均不同,并不是所有的子类都需要返回视图View,有些直接返回流,有些返回字符串等 ...
- Android使用SAX解析XML(2)
school类包含了一个major列表,可以增加该列表的元素,以及返回该列表,还实现了Parcelable.Creator接口. package com.hzhi.my_sax; import jav ...