美文网首页
iOS webView利用NSURLProtocol实现离线缓存

iOS webView利用NSURLProtocol实现离线缓存

作者: 林神_iOS | 来源:发表于2018-07-13 16:42 被阅读0次

    前言

            最近公司有一个需求,要对webView(UIWebView)实现缓存机制。即在无网条件下,打开webView页面,能读取到网页,有网情况下,缓存未过期也可以使用本地缓存,加快用户读取网页速度。

            实现缓存策略的方案有很多,为了保证有效,可控等多方面因素,本文采用NSURLProtocol来实现该需求,它的优势很多,楼主就不再累述了。

            关于NSURLProtocol,网上给出了很多资料,但很多方案都有缺陷,包括github上有star的项目,会遇到在特定情况下,网页加载不出来的问题,导致一直显示空白页。本文成功解决了这些问题,目前该项目已在线上稳定运行。

            写这篇文章,一方面为了自己,做一些整理,另一方面如果小伙伴,遇到类似需求后,不至于走太多弯路,所谓前人栽树,后人乘凉。废话不多说了,直接上内容。

    首先关于URL Loading System

    简单来说,URL Loading System是iOS一系列网络请求类的集合,包括老的NSConnection和现在流行的NSURLSession,还包括一些请求认证的类,一个sessionConfig的类,还有关于处理请求缓存的类等,当然也包括NSURLProtocol类。

    NSURLProtocol

    当我们需要拦截URL请求时,我们只要通过 - registerClass: 方法注册我们的NSURLProtocol类,然后去重写NSURLProtocol类中的方法,就能对我们发起的请求做处理。

    具体使用方法:

    1. 继承于NSURLProtocol

    NSURLProtocol 是一个抽象类,所以使用的时候必须定义一个它的子类:

    2. 注册

    需要拦截URL的控制器中注册该类:

    记得在不需要的时候,及时关闭它:

    注意一点:如果是基于 NSURLSession 进行的请求,注册的时候需要注册到 NSURLSessionConfiguration 中:

    3.子类必须实现的方法

    注册成功之后,需要子类CLURLSessionProtocol去实现抽象方法:

    + (BOOL)canInitWithRequest:(NSURLRequest*)request

    此处可以拦截需要处理的URL,已经处理过的请求,需要标记请求是否被处理过,防止死循环

    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request

    这个方法用来统一处理请求 request 对象的,可以修改头信息,或者重定向。没有特殊需要,则直接return request;

    如果要在这里做重定向以及头信息的时候注意检查是否已经添加,因为这个方法可能被调用多次,也可以在后面的方法中做。

    + (BOOL)requestIsCacheEquivalent:(NSURLRequest*)a toRequest:(NSURLRequest*)b

    判断网络请求是否一致,一致的话使用缓存数据。没需要就调用 super 的方法。

    - (void)startLoading

    这个方法作用很大,把当前请求的request拦截下来以后,在这个方法里面对这个request做各种处理,比如添加请求头,重定向网络,使用自定义的缓存等。

    重点:需要标记已经处理过的 request:

    - (void)stopLoading

    取消流程

    4.整理下业务需求:

    流程图:

    相关文章

      网友评论

          本文标题:iOS webView利用NSURLProtocol实现离线缓存

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