iOS webView 远程html加载本地资源
昨天,一个朋友让我帮他在IOS上弄这样一件事情:
webView 调用远程URL,并且让远程的web 通过自定义标签能实现内嵌本地的图片、js 或音频等。
比如:在服务器端 的html文件中 这样写到
<html>
<body>
<h1>we are loading a custom protocl</h1>
<b>image?</b><br/>
<img src="myapp://image1.png" />
<body>
</html>
那么当这个页面被iOS 中webView 显示的时,当渲染到 myapp://image1.png 的自定义标签的时候能将本地的图片资源 替换进去。这样的好处就是在网络上无需传输图片,性能比较高。
我朋友的项目是基于cordova 框架,一开始我还不是很理解他为什么说要远程web 调用本地资源,在我的脑海里面就是:“这个框架js 不都是本地的吗????”
,然后他告诉我是他在cordova 框架中导航到 自己的web 服务器。 我听了之后就只能用“呵呵” 表示了,好吧...也就不管了。
那么我就想到其实cordova框架就是基于webView 的一个事件拦截和封装的。 其实它是对NSURLProtocol 的自定义累进行注册,那么所有的webview 对http请求都会被他拦截到;
这里我们可以做很多事情;
接下来我们自己做自己的 NSURLProtocol 累吧
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
@interface NSURLProtocolCustom : NSURLProtocol //在项目中添加自定义NSURLProtocolCustom 并且继承NSURLProtocol
{
}
//实现中重现如下几个方法
@implementation NSURLProtocolCustom
//重写方法 1
+(BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSLog(@"canInitWithRequest");
// 这里是html 渲染时候入口,来处理自定义标签 如 "myapp",若return YES 则会执行接下来的 -startLoading方法
if ([request.URL.scheme caseInsensitiveCompare:@"myapp"] == NSOrderedSame||
[request.URL.scheme caseInsensitiveCompare:@"app"] == NSOrderedSame) {
return YES;
}
return NO;
}
//重写方法
+(NSURLRequest*)canonicalRequestForRequest:(NSURLRequest *)request
{
NSLog(@"canInitWithRequest");
return request;
}
//重写方法
-(void)startLoading
{
//处理自定义标签 ,并实现内嵌本地资源
NSLog(@"startLoading");
NSLog(@"%@", super.request.URL);
NSString *url=super.request.URL.resourceSpecifier;// 得到//image1.png"
//去掉 //前缀()
url=[url substringFromIndex:2];//image1.png
//若是app 协议 需要添加www (这里是我们自己业务上的吹)
if ([super.request.URL.scheme caseInsensitiveCompare:@"app"]) {
url=[[NSString alloc] initWithFormat:@"www/%@",url];
}
// NSString *path= [[NSBundle mainBundle] pathForResource:@"www/image1.png" ofType:nil];
NSString *path= [[NSBundle mainBundle] pathForResource:url ofType:nil];//这里是获取本地资源路径 如 :png,js 等
if (!path) {
return;
}
//根据路径获取MIMEType (以下函数方法需要添加.h文件的引用,)
// Get the UTI from the file's extension:
CFStringRef pathExtension = (__bridge_retained CFStringRef)[path pathExtension];
CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
CFRelease(pathExtension);
// The UTI can be converted to a mime type:
NSString *mimeType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType);
if (type != NULL)
CFRelease(type);
// 这里需要用到MIMEType
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:super.request.URL
MIMEType:mimeType
expectedContentLength:-1
textEncodingName:nil];
// NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"广告iOS" ofType:@"png"];
NSData *data = [NSData dataWithContentsOfFile:path];//加载本地资源
//硬编码 开始嵌入本地资源到web中
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
}
-(void)stopLoading
{
NSLog(@"something went wrong!");
}
@end
//类已经实现好了 那么怎样调用呢???
//其他代码都已经省略了,核心如下:
- (void)viewDidLoad {
[super viewDidLoad];
// 这里可以看出 只要注册一次就够了。。。我们可以将它写在delegate 入口就可以实现所有的请求拦截
[NSURLProtocol registerClass:[NSURLProtocolCustom class]];
//测试: 这里webView 我是直接从interface build 中引用过来的所以没有自定义实例化。
self.myWebView.backgroundColor = [UIColor redColor];
self.myWebView.scalesPageToFit =YES;
self.myWebView.delegate =self;
NSURL *url =[[NSURL alloc] initWithString:@"http://192.168.199.197/soqik/test.html"];//地址可以是远程地址也可以是本地的html 方法
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[self.myWebView loadRequest:request];
// Do any additional setup after loading the view, typically from a nib.
}
到这里为止远程web调用本地的js 或者图片资源已经完成了,接下来就是怎样在cordova 中进行改造。。。。原本以为在cordova中这样弄进去就可以了,但是发现这样是不行的,原因很简单:它们已经对 这个封装过,所以必须改造它们的对象。经过一定时间的研究 最终发现改造需要到:
CDVURLProtocol.h类中实现
那么这里需要注意的是:若资源找不到则需要调用Cordova封装的方法
//错误处理,而不是直接返回nil 不进行任何处理,这样会导致js 无法正常加载、运行
-(void)startLoading{
....//省略
if (!path) {
[self sendResponseWithResponseCode:401 data:nil mimeType:nil];//重要
return;
}
...//省略
//否则
NSData *data = [NSData dataWithContentsOfFile:path];
[self sendResponseWithResponseCode:200 data:data mimeType:mimeType];
}
好吧,表示完美解决。。。。cordova中可以干任何自己想弄的事情了
(参考资料:http://stackoverflow.com/questions/5572258/ios-webview-remote-html-with-local-image-files)
iOS webView 远程html加载本地资源的更多相关文章
- [IOS]UIWebView 请求网络页面或者加载本地资源页面
UIWebView是一个能够显示网页的IOS视图控件,我们可以用它来访问一个网站.下面是具体的实例: 操作步骤: 1.首先在xib文件中拖放一个UIWebView控件到view中 2.将下载的页面以及 ...
- iOS WebView 加载本地资源(图片,文件等)
https://www.cnblogs.com/dhui69/p/5596917.html iOS WebView 加载本地资源(图片,文件等) NSString *path = [[NSBundle ...
- 填补Resources和WWW加载本地资源的坑
总的来说Resources和WWW加载本地资源坑比较多,大多与路径有关. 下面代码构成了一个路径的预读模块: 此模块主要解决的坑是:Resources或WWW加载本地的文件夹中的多个文件时,无法获取文 ...
- 引入外部 CDN失效时--怎么加载本地资源文件(本文以jquery为例)
相信大家都使用过CDN静态资源库,比如下面 CDN官方静态资源库:https://cdnjs.com/ 七牛前端公开库:http://staticfile.org (vue,react,nl都有) ...
- MFC CDHtmlDialog 加载本地资源
步骤:1.资源视图 项目右击选择资源添加,自定义添加新类型 如:JS(会增加JS文件夹)2. 选择1新建的文件夹右击 添加资源 导入 选择js文件引入3. 在资源文件Resource.h文件夹能找到资 ...
- qt webengineview 加载本地资源方式
一.如果把资源添加到本地资源qrc库里了,请使用 ui->preview->setUrl(QUrl("qrc:/HelloWorld2.html")): 二.如果没有现 ...
- ios中UIWebview中加载本地文件
[super viewDidLoad]; webview=[[UIWebView alloc] initWithFrame:self.view.bounds]; [self.view addSubvi ...
- 转:Android Webview 加载外部html时选择加载本地的js,css等资源文件
原文地址:http://m.blog.csdn.net/blog/qduningning/43196819 在使用WebView加载网页的时候,有一些固定的资源文件如js的jquery包,css,图片 ...
- 控件WebView网页的加载
Android:控件WebView网页的加载 WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWe ...
随机推荐
- 161216、使用spring的DefaultResourceLoader自定义properties文件加载工具类
import java.io.IOException; import java.io.InputStream; import java.util.NoSuchElementException; imp ...
- Process and Thread
A process is a completely independent program that has its own address space, while a thread is a se ...
- 给tabBar设置图片和字体颜色的几种方法
现在很多应用都使用到了tabBar,我们往往在给tabBar设置图片和字体的时候,当选中状态下,往往字体的颜色和图片的颜色不匹配,有时候就显得无从下手,我也常常忘了,所有写这个博客的目的,相当于给自己 ...
- # TypeScript 中如何确保 this 的正确性
问题 在 TS 里面 this 关键字一开始让我这个写 C# 的十分惊讶,比如下面的一段代码,注意 initBinding 方法 class Company { id:number; /** * 在点 ...
- Json概述以及python对json的相关操作(转)
什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...
- 2. Swift元组|可选值|断言
1. 元组英文名字 Tuple,将多个数据类型(任意类型)组合成一个数据,与c语言的中的机构体有几分相似,功能也是非常强大的,尤其是在定义请求参数,状态之类的地方经常用到. let http404Er ...
- java 导出Excel 大数据量,自己经验总结!(二)
在上一次的基础上加上了样式,以及中文列名 package com.tommy.fundation.util; import java.io.OutputStream; import java.util ...
- C#程序设计---->计算圆面积windows程序
值得说的就是添加一个回车事件, http://blog.csdn.net/nanwang314/article/details/6176604 private void textBox1_KeyDow ...
- centos使用yum安装mysql
参考:http://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/ 1.增加yum数据源 (1.1)从http://dev.mysql.com/dow ...
- day 2
三目运算符 A?B:C 等价于 if(A) B; else C; 实例: int i: i=(3>2?5:1) //如果3>2为真,i的值为5,否则为1 printf(“%d”,i): ...