iOS Webview 与 app交互
有时候我们在内嵌的webview中希望点击一个链接之后,触发iOS原生事件,而不是webview内页面跳转(因为webview的跳转很生硬,而ajax+js模拟则不如原生segue平滑)。
有时候我们希望在页面内consloe.log('log something')
的时候在控制台里看到输出,但手机里没有控制台,所以我们希望可以利用xcode的控制台输出信息。
因为iOS没有提供API让我们直接用html或者js来跟外部交互,所以我们必须用另外一种巧妙的办法来实现这两个功能。这种方法可以满足我们两种需求。
console.log
在html页面中重新定义console.log
:
<script>
// Debug
console = new Object();
console.log = function(log) {
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "ios-log:#iOS#" + log);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;
</script>
然后在需要捕获的viewController.m中实现协议:
- (BOOL)webView: (UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
//NSLog(requestString);
if ([requestString hasPrefix:@"ios-log:"]) {
NSString* logString = [[requestString componentsSeparatedByString:@":#iOS#"] objectAtIndex:];
NSLog(@"UIWebView console: %@", logString);
return NO;
}
return YES;
}
当然前提是webView需要把委托设定为当前控制器:
self.webView =[[UIWebView alloc] initWithFrame:CGRectMake(0.0f,0.0f,self.view.bounds.size.width,self.view.bounds.size.height-)];
self.webView.delegate=self;
原理很简单,我们重新定义了console.log
函数,还有console.debug
,console.info
,console.warn
,console.error
。当我们在页面js中调用console.log
的时候,就会创建一个iframe发出请求,请求的协议为ios-log:
,路径就是我们的log字符串。发出请求之后,迅速把这个iframe清理掉。
这样,在webview中我们发出了一个请求,然后就没了。外部我们用objective-c实现了一个协议,就是webview开始发出请求之前就会调用的函数。在这个函数中我们过滤所有的请求(因为除了ios-log
,还有一些“正常”的请求比如http和mailto),当前缀为ios-log
的时候,我们就NSLog
即可。
if
最后的return NO
的意思是该webview的请求被捕获,不再请求(这个实际上不存在的页面)。我们希望一些合法请求(比如http、mailto等)不被捕获,所以最后if
外面丢了一个return YES
。
webview中的代码:
<a href="myapp://somepagename">一个按钮</a>
非常简单,myapp这个协议你可以自己随便命名,稍后我们会在objective-c中捕获它。
还是要实现该webview的委托controller的协议方法,如果你已经定义这个方法了(就像上面那个例子),你只需要在方法体里加入方法体里面的内容,否则会提醒你重复定义。
- (BOOL)webView: (UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = [request URL];
if ( [[url scheme] isEqualToString:@"myapp"] )
{
NSString *slug = [url path];
[self performSegueWithIdentifier:@"heroSegue" sender:slug];
return NO;
}
return YES;
}
另外我在interface builder中已经拖拽了一个新的控制器,在新的控制器跟导航控制器之间,我直接拖了一个segue,命名id为heroSegue
,所以这里可以用performSegueWithIdentifier
来调用segue。
现在,还是在本controller中,我们实现另一个委托方法:
/*
* 页面转换时触发
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"heroSegue"]) {
NSLog(@"%@",sender);
[self.webView stopLoading];
YUGHeroDetailViewController *destViewController = segue.destinationViewController;
destViewController.heroSlug = (NSString *)sender;
}
}
也就是说,发生segue变化之前,就会执行这一方法,首先判断identifier是不是等于heroSegue,如果是,自己的webview不再载入,目标控制器(也就是即将切换过去的子页面的控制器)中设置公有属性heroSlug的值。
然后,我们在目标页面的controller的H中定义:
@property (strong) NSString *heroSlug;
最后,在目标页面中,我们定义的congroller中的M能拿到heroSlug这个参数。
NSLog(@"%@",self.heroSlug);
这样就可以了,拿到slug之后,我们实际上就可以调用一个本地页面,带上slug参数,然后通过ajax的方式读取远程页面或者json数据,这个就不属于本文内容了。
如果你是新手,在做上面的这些操作的时候可能会漏掉一两个步骤,编辑器会报错,这时候仔细阅读并校对你的代码。如果实在不行,说明清楚操作和报错信息,再给我留言。
练习题:原生title的好处是它在字符数较短时是居中的,而字符更长一点时会偏右显示,更长一些时显示省略号。那么webview载入一个ajax数据的页面的时候,如何在页面载入成功时,设置原生title?
提示,还是自定义协议。
iOS Webview 与 app交互的更多相关文章
- iOS webView与js交互在文本空格上输入文字
项目要求:webview加载html网址,内容为填空题型文本,需要在横线上添加答案,并点击提交按钮后再将答案进行回显 正常加载的效果图片: 这个是用js交互后的效果图: 点击空格,输入想输入的答案,如 ...
- andriod/ios webview与js交互 html_demo
<html> <head> <title>测试</title> </head> <body> <h3>Android ...
- iOS与JS开发交互总结
hybrid.jpg 前言 Web 页面中的 JS 与 iOS Native 如何交互是每个 iOS 猿必须掌握的技能.而说到 Native 与 JS 交互,就不得不提一嘴 Hybrid. Hybri ...
- h5 与原生 app 交互的原理
现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次就来捋 ...
- 客户端相关知识学习(二)之h5与原生app交互的原理
前言 现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次 ...
- h5与app交互
现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次就来捋 ...
- webview和H5交互
由于H5的灵活多变,动态可配的特点,也为了避免冗长 的审核周期,H5页面在app上的重要性正日益突显. iOS应用于H5交互的控件主要是UIWebView及WKWebView WKWebView是14 ...
- Android混合开发之WebView与Javascript交互
前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...
- 分分钟解决iOS开发中App启动广告的功能
前不久有朋友需要一个启动广告的功能,我说网上有挺多的,他说,看的不是很理想.想让我写一个,于是乎,抽空写了一个,代码通俗易懂,简单的封装了一下,各种事件用block回调的,有俩种样式的广告,一种是全屏 ...
随机推荐
- iphone丢了以后发现关机了怎么办?
有好几个办法都可以尝试一下: 1. "ICCID法",但目前这个办法只能寻找苹果iPhone手机,而对于安卓手机,则不能采取相同的方法进行寻找.之所以能采取该方法寻找苹果 iPho ...
- Lenovo笔记本电脑进入BIOS的方法
使用NOVO键开机进入BIOS的操作方法 适用范围:2012年后发布的部分笔记本产品,含:IdeaPad全系列.Lenovo G系列部分IdeaPad U或S系列,YOGA/FLEX全系列产品Leno ...
- x86保护模式 控制寄存器和系统地址寄存器
控制寄存器和系统地址寄存器 控制寄存器 crx cr0 指示cpu工作方式的控制位 包含启用和禁止分页管理机制的控制位 包含控制浮点协处理器操作的控制位 注意必须为0的位 cr2和c ...
- php(ajax)异步刷新(转)
第一种方法,ajax实现:当然,ajax使用起来确实很简单就可以实现,但是里面的很多知识还是比较有点深的.我之前做页面时间自动刷新的功能就是用的ajax.完整代码是:1.getTime.php: 复制 ...
- 网页QQ唤起
网页QQ唤起 <html> <head> <meta http-equiv="Content-Type" content="text/htm ...
- [Kubernetes]深入解析Pod
Pod是Kubernetes项目的原子调度单位 为什么需要Pod? 容器是未来云计算系统中的进程,容器镜像就是这个系统里的".exe"安装包,那Kubernetes就是操作系统. ...
- "sort open failed +1 no such file or directory"解决方
GNU的sort也认老式字段规格: +n.m. 但是字段和字符都从0开始计, 例如-k3 -k2可以等效为+2 -3 +1 -2. 目前使用的sort+和-必须成对使用, 只用+就会报错说”sort: ...
- [luoguP2606] [ZJOI2010]排列计数(DP)
传送门 如果能够根据题意看出这是一个堆的话,那么就有些思路了.. 首先堆顶必须是最小元素,然后左右儿子可以预处理出来都有多少个数, 把剩余的数任意分配给两个儿子,用排列组合即可 dp(now) = d ...
- POJ 1330:Nearest Common Ancestors【lca】
题目大意:唔 就是给你一棵树 和两个点,问你这两个点的LCA是什么 思路:LCA的模板题,要注意的是在并查集合并的时候并不是随意的,而是把叶子节点合到父节点上 #include<cstdio&g ...
- 刷题总结——赛车(bzoj3190)
题目: 题目背景 JLOI2013 T1 题目描述 这里有一辆赛车比赛正在进行,赛场上一共有 N 辆车,分别称为 g1,g2,……,gn.赛道是一条无限长的直线.最初,gi 位于距离起跑线前进 ki ...