从WebView跳到普通View
本文转载至 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的更多相关文章
- 小程序webview跳转页面后没有返回按钮完美解决方案
		
随着小程序越来越火爆,使一个产品如果只有公众号H5页面和APP显得不怎么完美,总感觉不搭上小程序这趟流量车,就会少了点什么,心里别扭地很.在此驱动下,我所在公司也决定赶紧上车. 但是,如果要按照小程序 ...
 - WebView跳转到底部
		
webview中有个computeVerticalScrollRange方法,是protected的,可以用反射,也可以自己写一个view继承webview,实现computeVerticalScro ...
 - 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 ...
 - 如何处理webView跳转
		
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error { // Give iOS a chance to o ...
 - jfinal取消默认跳转到view.jsp页面的方法
		
今天为了在一个列表中添加一个删除的方法,直接在方法里面谢了一个dao.del();方法,但是调用的时候却出现404错误. 然后就写了一句下面的代码 redirect("/api/listMe ...
 - iOS悬浮窗口(无论界面跳转、View始终在视图上显示,可移动)
		
2016.09.24 23:52* 字数 71 阅读 5925评论 9喜欢 11 让所有界面都显示,最好还是封装一个继承Window的类:JYCWindow. 先看看效果: mygif.gif 关 ...
 - 最简单webview跳转
		
String url = "http://www.qq.com" Uri uri=Uri.parse("http://www.baidu.com"); Inte ...
 - 浅谈URL跳转与Webview安全
		
学习信息安全技术的过程中,用开阔的眼光看待安全问题会得到不同的结论. 在一次测试中我用Burpsuite搜索了关键词url找到了某处url,测试一下发现waf拦截了指向外域的请求,于是开始尝试绕过.第 ...
 - URL跳转与webview安全浅谈
		
URL跳转与webview安全浅谈 我博客的两篇文章拼接在一起所以可能看起来有些乱 起因 在一次测试中我用burpsuite搜索了关键词url找到了某处url我测试了一下发现waf拦截了指向外域的请求 ...
 
随机推荐
- python --curl重定向到文件范例
			
import sys import os import subprocess import time start = time.time() old=sys.stdout f=open('test ...
 - Android成长之路-手势库的创建
			
手势库的创建: 使用SDK自带的例子GestureBuilder建立手势库,这个文件夹存在于android\android-sdk-windows \samples\android-10\Gest ...
 - 如何用C#做一个悬浮窗口程序
			
用C#做一个像FlashGet的悬浮窗口,其实很简单,不像以前需要调用很多系统API.大致的步骤如下. 首先是主窗体部分,即要判断窗体的状态来决定是否显示悬浮窗口. 局部成员声明: private F ...
 - Faster RCNN原理分析 :Region Proposal Networks详解
			
博主的论文笔记: https://blog.csdn.net/YZXnuaa/article/details/79221189 很详细! 另外,关于博主的博客很多拓展知识面: 120篇 深度学习23篇 ...
 - <class 'Salesman.admin.UsrUserAdmin'>: (admin.E012) There are duplicate field(s) in 'fieldsets[0][1]'.
			
ieldsets = ( ['Main', { 'fields': ('user_name', 'real_name', 'concat_name','phone_no','charge_person ...
 - webpack One CLI for webpack must be installed. These are recommended choices, delivered as separate(webpack报错)
			
用webpack 打包项目的时候:webpack js.js bundle.js 报错. 最近在安装好webpack后,使用时,提示 One CLI for webpack must be insta ...
 - apache 静态编译和动态编译参考
			
apache-2.2.22 编译安装笔记 一.静态编译 在使用./configure 编译的时候,即没有使用--enable-mods-shared=[module]或者--enable-[m ...
 - Java Main如何被执行?
			
java应用程序的启动在在/hotspot/src/share/tools/launcher/java.c的main()函数中,而在虚拟机初始化过程中,将创建并启动Java的Main线程.最后将调用J ...
 - 源码分析HotSpot GC过程(二):DefNewGeneration的GC过程
			
由于虚拟机的分代实现,虚拟机不会考虑各个内存代如何实现垃圾回收,具体的工作(对象内存的分配也是一样)由各内存代根据垃圾回收策略自行实现. DefNewGeneration的使用复制算法进行回收.复制算 ...
 - cxf动态调用webservice设置超时,测试线程安全
			
Java代码 import java.util.Random; import java.util.concurrent.ArrayBlockingQueue; import java.util.con ...