本文转载至 http://pingguohe.net/2011/06/25/webview_to_nativeview/

做网络ios应用难免要用到UIWebViewController,直接嵌入一个html页面。这种native+web的方式再很多app中都有应用,app store就是一个,另外如淘宝iPhone客户端的支付,口碑网iPhone客户端的团购内容,等等。这种实现方式,某种程度上牺牲了一些体验,但大大提高了开发效率,而且降低了升级成本。这种方式非常适合实现一个仍处在发展初期的功能。

但使用native+web的方式有一个最大的问题,就是从WebView向NativeView的跳转。由于进入WebView后,页面中的链接都是web控制,所有点击都将在web框架内进行,无法返回到NativeView,给WebView的使用造成很大局限。这里介绍一下如何实现从WebView向NativeView的跳转。

实现原理很简单,在内嵌的页面里写一个规定格式的超链接,在WebViewController里抓载入状态,判断URL是否为约定的,按照约定跳转到相应的NativeView。

具体实现,先看WebViewDelegate里的几个方法:

- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
 
- (void)webViewDidStartLoad:(UIWebView *)webView;
 
- (void)webViewDidFinishLoad:(UIWebView *)webView;
 
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;

这四个方法分别在不同时机被调用。第一个方法在页面请求发出之前被调用,第二个和第三个方法分别再页面内容开始载入和载入完成时被调用,最后一个是载入失败时被调用。

要抓请求状态需要在第一个方法中。因为页面中所写的URL是应用开发者约定的格式,而不是HTTP请求,因此这个请求无法成功发送,那么也就不会调用到第二和第三个方法,第四个方法用于异常处理,所以只能在第一个方法中抓请求状态。通过第一个方法的request参数,拿到request.URL,这个URL就是我们写在WebView上的,那么WebViewController就可以根据约定,判断出要跳转的NativeView,通过NavigationController跳转,或是实现其他逻辑。

在约定URL的时候还要注意,这个URL一定不要定义成一个HTTP请求。WebViewController就会自动处理HTTP请求,把请求发出去,页面也会发生重新载入,而这个请求是指向NativeView的,也就是不存在与Internet上,所以页面将出现404状态。

另外,如果WebView上指向NativeView的不是一个超链接,通过javascript方式也可以实现这个功能。只要通过JS把页面跳转到之前提到过的约定格式的URL就可以了。通过JS的方式,还可以实现WebView到NativeView的自动跳转。

—— Jul. 4, 2011 ——

附送把URL拆解的代码一份

ExtString.h

 
#define PROTOCOL @"PROTOCOL"
#define HOST @"HOST"
#define PARAMS @"PARAMS"
#define URI @"URI"
 
@interface ExtNSString : NSString {
}
 
@end
 
@interface NSString (ExtNSString)
 
/**
* @param NSString *URL 需要解析的URL,格式如:http://host.name/testpage/?keyA=valueA&keyB=valueB
* @return NSDictionary *params 从URL中解析出的参数表
* PROTOCOL 如 http
* HOST 如 host.name
* PARAMS 如 {keyA:valueA, keyB:valueB}
* URI 如 /testpage
*/
- (NSDictionary *)paramsFromURL;
 
@end

ExtString.m

#import "ExtNSString.h"
 
@implementation NSString (ExtNSString)
 
- (NSDictionary *)paramsFromURL {
 
NSString *protocolString = [self substringToIndex:([self rangeOfString:@"://"].location)];
 
NSString *tmpString = [self substringFromIndex:([self rangeOfString:@"://"].location + 3)];
NSString *hostString = nil;
 
if (0 < [tmpString rangeOfString:@"/"].length) {
hostString = [tmpString substringToIndex:([tmpString rangeOfString:@"/"].location)];
}
else if (0 < [tmpString rangeOfString:@"?"].length) {
hostString = [tmpString substringToIndex:([tmpString rangeOfString:@"?"].location)];
}
else {
hostString = tmpString;
}
 
tmpString = [self substringFromIndex:([self rangeOfString:hostString].location + [self rangeOfString:hostString].length)];
NSString *uriString = @"/";
if (0 < [tmpString rangeOfString:@"/"].length) {
if (0 < [tmpString rangeOfString:@"?"].length) {
uriString = [tmpString substringToIndex:[tmpString rangeOfString:@"?"].location];
}
else {
uriString = tmpString;
}
}
 
NSMutableDictionary* pairs = [NSMutableDictionary dictionary];
if (0 < [self rangeOfString:@"?"].length) {
NSString *paramString = [self substringFromIndex:([self rangeOfString:@"?"].location + 1)];
NSCharacterSet* delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&;"];
NSScanner* scanner = [[[NSScanner alloc] initWithString:paramString] autorelease];
while (![scanner isAtEnd]) {
NSString* pairString = nil;
[scanner scanUpToCharactersFromSet:delimiterSet intoString:&pairString];
[scanner scanCharactersFromSet:delimiterSet intoString:NULL];
NSArray* kvPair = [pairString componentsSeparatedByString:@"="];
if (kvPair.count == 2) {
NSString* key = [[kvPair objectAtIndex:0]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString* value = [[kvPair objectAtIndex:1]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[pairs setObject:value forKey:key];
}
}
}
 
return [NSDictionary dictionaryWithObjectsAndKeys:
pairs, PARAMS,
protocolString, PROTOCOL,
hostString, HOST,
uriString, URI, nil];
}
 
@end
 
@implementation ExtNSString
@end

从WebView跳到普通View的更多相关文章

  1. 小程序webview跳转页面后没有返回按钮完美解决方案

    随着小程序越来越火爆,使一个产品如果只有公众号H5页面和APP显得不怎么完美,总感觉不搭上小程序这趟流量车,就会少了点什么,心里别扭地很.在此驱动下,我所在公司也决定赶紧上车. 但是,如果要按照小程序 ...

  2. WebView跳转到底部

    webview中有个computeVerticalScrollRange方法,是protected的,可以用反射,也可以自己写一个view继承webview,实现computeVerticalScro ...

  3. WebView in ScrollView:View not displayed because it is too large to fit into a software layer

    报错信息 W/View: WebView not displayed because it is too large to fit into a software layer (or drawing ...

  4. 如何处理webView跳转

    - (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {    // Give iOS a chance to o ...

  5. jfinal取消默认跳转到view.jsp页面的方法

    今天为了在一个列表中添加一个删除的方法,直接在方法里面谢了一个dao.del();方法,但是调用的时候却出现404错误. 然后就写了一句下面的代码 redirect("/api/listMe ...

  6. iOS悬浮窗口(无论界面跳转、View始终在视图上显示,可移动)

    2016.09.24 23:52* 字数 71 阅读 5925评论 9喜欢 11 让所有界面都显示,最好还是封装一个继承Window的类:JYCWindow. 先看看效果:   mygif.gif 关 ...

  7. 最简单webview跳转

    String url = "http://www.qq.com" Uri uri=Uri.parse("http://www.baidu.com"); Inte ...

  8. 浅谈URL跳转与Webview安全

    学习信息安全技术的过程中,用开阔的眼光看待安全问题会得到不同的结论. 在一次测试中我用Burpsuite搜索了关键词url找到了某处url,测试一下发现waf拦截了指向外域的请求,于是开始尝试绕过.第 ...

  9. URL跳转与webview安全浅谈

    URL跳转与webview安全浅谈 我博客的两篇文章拼接在一起所以可能看起来有些乱 起因 在一次测试中我用burpsuite搜索了关键词url找到了某处url我测试了一下发现waf拦截了指向外域的请求 ...

随机推荐

  1. mybatis WARN No appenders could be found for logger的解决方法

    log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).log4j:WARN ...

  2. 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测

    如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...

  3. atoi 和 itoa

    转自:http://www.cnblogs.com/cobbliu/archive/2012/08/25/2656176.html atoi 和 itoa是面试笔试经常要考到的题目,下面两份代码是用C ...

  4. AutoFac文档5(转载)

    目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 扫描 autofac可 ...

  5. 如何实现php异步处理

    在实际生成环境下,php作为后台的接口服务器已经很常见,php当然具有它能作为后台服务器的优势之处,但是,在处理一些客户端并不关心的结果时,就显出它的弊端了---没有异步执行的机制.就比如我们想做一些 ...

  6. unity, 如果碰撞使用2d物理,为防止颤动,需将更新position的代码写在FixedUpdate里

    例如我为主角添加了一个circle collider 2d,和一个rigidbody 2d,为障碍物添加了一个circle collider 2d. 然后我在主角的Update函数里更新位置让主角由A ...

  7. [Jobdu] 题目1544:数字序列区间最小值

    题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的开头为一个整数n(1<=n<=100000),代表数字序列的长度.接下去一行给出 ...

  8. find_if查找vector内对象的成员 作为菜鸟一直不会用也不敢用

    用stl的find方法查找一个包含简单类型的vector中的元素是很简单的,例如 vector<string> strVec; find(strVec.begin(),strVec.end ...

  9. 关于DebuggerHidden特性在Unity中的使用

    经过测试,DebuggerHidden只对输出的日志有影响.对编辑器的控制台输入没有影响 你可以通过这个特性避免日志log有一堆的堆栈信息 并且测试过发现Debug.LogError也不支持该特性,和 ...

  10. Activity生命运行中的几个方法

    给大家看看一个周期图