让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

推荐文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 通过学习,你将会学习以下几个方面的内容: **什么是WKWebView以及它和UIWebView的区别是什么 **...
    SOI阅读 11,817评论 18 42
  • 前言 关于UIWebView的介绍,相信看过上文的小伙伴们,已经大概清楚了吧,如果有问题,欢迎提问。 本文是本系列...
    CoderLF阅读 9,096评论 2 12
  • UIWebView 之痛 开发App的过程中,常常会遇到在App内部加载网页,通常用UIWebView加载。而这个...
    zyl04401阅读 16,157评论 46 157
  • 转载:http://www.cnblogs.com/NSong/p/6489802.html 导语 WKWebVi...
    李小威阅读 4,913评论 8 9
  • WKWebView 是苹果在 WWDC 2014 上推出的新一代 webView 组件,用以替代 UIKit 中笨...
    Aiana阅读 4,674评论 1 8