最近项目中有这样一个小需求:用远程h5页面展示本地的照片。
问题:远程的h5页面显示远程的图片(.jpg/.png等)可以正常显示;但是如果图片在本地,那么h5中的图片无法加载和显示。
解决思路有两个:
(1)在oc端写一个读取本地图片的接口,当h5需要显示本地图片时,在js端调用oc端显示图片的接口;
(2)在request请求时进行拦截,拦截满足条件的请求并处理,将本地图片写入流并response给h5。
我这里用的第二种方法实现的,所以这里重点讲第二种方法。
IOS中我们经常使用的网络请求NSURLConnection以及WebView的页面加载都会被NSURLProtocol截获。NSURLProtocol 是IOS中非常重要的一个部分,我们经常会在以下地方用到它:
(1)网络请求代理转发(翻墙 网络加速等);
(2)离线缓存策略。
简单介绍下NSURLProtocol经常用到的几个方法:
(1)+ (BOOL)canInitWithRequest:(NSURLRequest *)request
功能:所有NSURLConnection请求的入口。
通过此方法来检测是否要拦截处理该请求,如果return YES就处理请求,代码会执行到startLoading函数中,如果是return NO就不处理请求。
此重写函数被执行的条件是继承于NSURLProtocol类并注册,后续会讲如何注册。
(2)+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest *)request
功能:更新请求。
一般情况下我们是不会去更改这个请求的,直接返回request。如果你想更改,比如给这个request添加一个title,组合成一个新的http请求。
(3)+ (BOOL)requestIsCacheEquivalent:(NSURLRequest )a toRequest:(NSURLRequest )b
功能:NSURLProtocol缓存系统设置。
如果有两个URL请求,并且他们是相等的,那么这里可以使用相同的缓存空间。
(4)- (void)startLoading
功能:获取网站上的数据建立connect连接。
通常是在这里处理请求,如:将满足scheme条件的请求的响应替换成本地资源的二进制文件并reponse给前端h5等。
(5)- (void)stopLoading
功能:当前Connection连接取消或请求失败的时候被调用。
特别注意:在本地NSURLRequest初始化的时候,有一个超时时间,在低速网络下,有可能页面还没来得及加载完,这个StopLoading方法也会被调用了。
下面是Demo代码。
服务器的webview4h5.html文件代码:
<!DOCTYPE html>
<html>
<hea