UIWebView 加载本地 CSS,JS

2017-12-10  本文已影响7人  ZHK1024

前言

之前使用UIWebView或者WKWebView加载本地CSS JS时候直接:

// html 为其他途径获取到的 html 字符串
NSURL *baseURL = [NSURL URLWithString:[NSBundle mainBundle].bundlePath];
[_webView loadHTMLString:html baseURL:baseURL];

设置一下 baseURL就能轻松加载到相对路径下的CSS JS资源文件.
但是这次却遇到了比较特殊的情况:

正文

问题

所谓的特殊情况就是这次我拿到的html是由Markdown转换过来的html字符串,本身包含有完整的URL信息.比如这样的内容.

// img 标签
<img src="http://img.google.com/image.png">

// 其他引入的 css, js 等
<script src="http://cdn.google.com/keymaster.min.js" type="text/javascript"></script>
<link href="http://cdn.google.com/prism.css" rel="stylesheet" type="text/css" />

在这种情况下:

既有相对路径,又有完整URL的时候.

设置了baseURL就会导致这些有完整URL图片,JS,CSS等内容不能够正常加载.

解决办法

思路
  1. 把所有的相对路径都补充成完整的URL.
  2. 通过NSURLProtocol来拦截请求并替换内容达到需求目的.
做法

此处不介绍NSURLProtocol用法,直接说解决办法:
如果原来资源文件的相对路径为/jquery.js.
那么现在把相对路径的路径全部补全为http://cdn.zhk1024.com/jquery.js.
此时URLhost则为cdn.zhk1024(此处host可以根据自己情况来写).
则在+ (BOOL)canInitWithRequest:方法内过滤hostcdn.zhk1024的所有请求,此类请求都是需要拦截的对象.
此处补全的 host 必须是在应用内没有使用过的域名

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    if ([request.URL.host isEqualToString:@"cdn.zhk1024"]) {
        // 此处返回 YES, 则该请求会进入 - (void)startLoading 方法 
        return YES;
    }
    return NO;
}

然后在- (void)startLoading方法内对拦截下来的请求进行处理
此处主要是通过判断URL等能够区分出请求的特征来分别加载资源文件(CSS JS等),然后把数据提交给 URL加载系统 (URL Loading System).

- (void)startLoading {
    id <NSURLProtocolClient> client = [self client];
    NSURLRequest *request = self.request;
    NSString *path = [[request URL] absoluteString];
    NSString *fileToLoad = nil;
    
    if ([path isEqualToString:@"http://cdn.zhk1024/reset.css"]) {
        fileToLoad = [[NSBundle mainBundle] pathForResource:@"reset" ofType:@"css"];
    }
    ....
    其他判断此处省略
    ....
    // 加载本地文件的数据
    NSData *data = [NSData dataWithContentsOfFile:fileToLoad];
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:[NSDictionary dictionary]];
    [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [client URLProtocol:self didLoadData:data];
    [client URLProtocolDidFinishLoading:self];
}

到此我们要做的事情就做完了,其他全部交给UIWebView即可.

此处之所有没有写WKWebView是因为WKWebViewNSURLSession 如果使用NSURLProtocol的话需要一些特殊设置.
WKWebView支持NSURLProtocol更是需要使用一些私有 API,一方面是苹果审核问题,另一方面是私有 API稳定性没有保障.
因此最终选择了UIWebView.

上一篇下一篇

猜你喜欢

热点阅读