让WebKit支持URLProtocol拦截实现WebP省流量方案《WKWebView不再从入门到放弃》

WKWebView的各种好处,有不少开发者都按捺不住骚动的心,开始操刀在项目里将UIWebView替换成WKWebView,然后就出现了《WKWebView从入门到放弃》其中WKWebView不支持NSURLProtocol就让不少开发者望而却步。这样一样,可能会导致原来UIWebView的省流量方案不生效。直到前几天,我看到了大神的这篇文章WKWebView 不支持 NSURLProtocol 吗。大神从底层分析了,WKWebView不走NSURLProtocol的原因,最后得出的结论是WebKit是支持NSURLProtocol的,只是WebKit还不够完成,另外一点是调用了私有API很可能被拒,也只支持iOS8.4+。

WKWebView的特性:

  • WKWebView的性能想必不用多说了 在性能、稳定性、功能方面有很大提升,直观体现是内存占用变少;
  • 允许JavaScript的Nitro库加载并使用(UIWebView中限制);
  • 支持了更多的HTML5特性;
  • 高达60fps的滚动刷新率以及内置手势;
  • 将UIWebViewDelegate与UIWebView重构成了14类与3个协议;

NSURLProtocol工作原理

NSURLProtocol可以拦截监听每一个URL Loading System中发出request请求,记住是URL Loading System中那些类发出的请求,也支持AFNetwoking,UIWebView发出的request。如果不是这些类发出的请求,NSURLProtocol就没办法拦截和监听了。

拦截代码

调用该代码则表示拦截成功,会将网页中图片地址转化成WebP格式,并由SDWebImageDownloader下载并缓存。

- (void)startLoading {
    NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
    //标示改request已经处理过了,防止无限循环
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
    NSString *URLString = [self.request.URL absoluteString];
    NSURL *imageURL;
    
    // 重定义请求地址
    if ([URLString rangeOfString:@"format"].location == NSNotFound) {
        imageURL = [WKWebImageHelper webImageStringToURL:URLString];
    }
    else {
        self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
        return;
    }
    
    #warning - 敲黑板 画重点了
    [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL
                                                          options:0
                                                         progress:nil
                                                        completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
                                                            // 是否以png结尾
                                                            if ([imageURL.absoluteString.lowercaseString hasSuffix:@".png"]) {
                                                                data = UIImagePNGRepresentation(image);
                                                            } else {
                                                                data = UIImageJPEGRepresentation(image, 1);
                                                            }
                                                            if (!self.client) {
                                                                return ;
                                                            }
                                                            [self.client URLProtocol:self didLoadData:data];
                                                            [self.client URLProtocolDidFinishLoading:self];
                                                        }];
}

具体的代码大家可以去我的github下载。下载地址在↓。

Demo截图

Simulator Screen Shot 2017年3月22日 下午5.22.58.png

Demo

  • 本文Demo:WebKitSupportURLProtocol
  • NSURLProtocol-WebKitSupport

推荐文章

  • HybridKit缓存及流量优化方案
  • WKWebView 那些坑
  • WKWebView 不支持 NSURLProtocol 吗

你可能感兴趣的:(让WebKit支持URLProtocol拦截实现WebP省流量方案《WKWebView不再从入门到放弃》)