美文网首页
UIWebView 加载本地 CSS,JS

UIWebView 加载本地 CSS,JS

作者: ZHK1024 | 来源:发表于2017-12-10 22:59 被阅读7次

    前言

    之前使用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.

    相关文章

      网友评论

          本文标题:UIWebView 加载本地 CSS,JS

          本文链接:https://www.haomeiwen.com/subject/dfmyixtx.html