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回调的,有俩种样式的广告,一种是全屏 ...
随机推荐
- PYDay10&11&12&13-常用模块:time|datetime|os|sys|pickle|json|xml|shutil|logging|paramiko、configparser、字符串格式化、py自动全局变量、生成器迭代器
1.py文件自动创建的全局变量 print(vars()) 返回值:{'__name__': '__main__', '__package__': None, '__loader__': <_f ...
- IOS 自动布局-UIStackPanel和UIGridPanel(二)
在上一篇中我提到了如何使用stackpanel和gridpanel来实现自动布局.而在这一篇中我着重讲解下其中的原理. 在(UIPanel UIStackPanel UIGridPanel)中主 ...
- 九度oj 题目1130:日志排序
题目描述: 有一个网络日志,记录了网络中计算任务的执行情况,每个计算任务对应一条如下形式的日志记录:“hs_10000_p”是计算任务的名称,“2007-01-17 19:22:53,315”是计算任 ...
- 九度oj 题目1534:数组中第K小的数字
题目描述: 给定两个整型数组A和B.我们将A和B中的元素两两相加可以得到数组C. 譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6]. 现在给你数组A和B ...
- 1.ruby基本格式
1.ruby对于空格是敏感的,很像shell 如:a + b 解释成 a+b(这是两个局部变量) a +b 解释成 a(+b) (这是一个方法调用) 2.在ruby中一行怎么才算结束? Ruby解释分 ...
- 栅格网络流(cogs 750)
[问题描述] Bob 觉得一般图的最大流问题太难了,他不知道如何解决,于是他想尝试一个简单点的:栅格网络中的最大流问题,这个虽说简单了一点,但对 Bob 来说依旧太难,现在他有个麻烦需要你帮忙:给你一 ...
- *AtCoder Regular Contest 096F - Sweet Alchemy
$n \leq 50$的树,每个点有权值,现要选点(可多次选一个点)使点数尽量多,如下限制:选的总权值不超过$C \leq 1e9$:$c_i$表示$i$选的次数,$p_i$表示$i$的父亲,那么$c ...
- msp430项目编程42
msp430综合项目---无线通信直流电机调速系统42
- nginx的配置文件 【nginx.conf】
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...
- 快速掌握RabbitMQ(一)——RabbitMQ的基本概念、安装和C#驱动
1 RabbitMQ简介 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现,官网地址:http://www.rabbitmq.com.Ra ...