美文网首页项目排查 问题
iOS web缓存策略以及手动清除缓存

iOS web缓存策略以及手动清除缓存

作者: taobingzhi | 来源:发表于2019-03-26 16:10 被阅读0次

    当我们使用webview加载html资源时,本质上就是向服务器索取资源的http请求过程,如果我们不注意资源的缓存策略的话,就可能会造成这样那样的问题,比如:实时性要求较高的功能却老是走缓存不更新,有些基本不会变动的页面却又每次都重新去服务器拉请求。

    使用缓存的基本思路:

    • 经常更新的内容,比如天气:不使用缓存,每次都请求最新数据;
    • 一成不变的内容:走缓存,节省流量,增加速度;
    • 偶尔更新:可以定期更改缓存策略或者清除缓存;

    提示:记得定期或者到一定缓存数量时,清除web缓存,清除方法在下方。

    NSURLRequestCachePolicy

    iOS自带的缓存策略,提供了一个内存和磁盘混合的缓存,一共有7种缓存策略,使用较多的是其中的四种(下方编号1,2,5,6

    1> NSURLRequestUseProtocolCachePolicy = 0, 默认的缓存策略, 如果缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端.
    
    2> NSURLRequestReloadIgnoringLocalCacheData = 1, 忽略本地缓存数据,直接请求服务端.
    
    3> NSURLRequestIgnoringLocalAndRemoteCacheData = 4, 忽略本地缓存,代理服务器以及其他中介,直接请求源服务端.
    
    4> NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData
    
    5> NSURLRequestReturnCacheDataElseLoad = 2, 有缓存就使用,不管其有效性(即忽略Cache-Control字段), 无则请求服务端.
    
    6> NSURLRequestReturnCacheDataDontLoad = 3, 死活加载本地缓存. 没有就失败. (确定当前无网络时使用)
    
    7> NSURLRequestReloadRevalidatingCacheData = 5, 缓存数据必须得得到服务端确认有效才使用(貌似是NSURLRequestUseProtocolCachePolicy中的一种情况)
    

    http的缓存

    上面介绍了iOS自带的缓存控制NSURLRequestCachePolicy,也说到当NSURLRequestCachePolicy设为默认的NSURLRequestUseProtocolCachePolicy时,主要是根据http的缓存策略来决定是否使用缓存。

    那么就简单的介绍一下,http的缓存控制和缓存校验。

    缓存控制:控制缓存的开关,用于标识请求或者访问中是否使用了缓存,使用了哪种缓存;
    缓存校验:如何校验缓存,比如怎么定义缓存的有效期,怎么确保缓存是最新的。

    缓存控制

    在http中,控制缓存开关的字段有两个,Pragma和Cache-Control

    Pragma

    Pragma有两个字段no-cache和expires,当pragma为no-cache时表示禁用缓存,expires的值是一个GMT时间,表示该缓存的有效时间。但是已经被逐步抛弃了,有些网站为了向下兼容还保留了这两个字段。

    Cache-Control

    Cache-Control除了在响应中使用,在请求中也可以使用。

    在请求中使用,Cache-Control可选的值有:


    Cache-Control请求.png

    在响应中使用,Cache-Control可选的值有:


    Cache-Control响应.png

    ps.no-store优先级最高
    在Cache-Control 中,这些值可以自由组合,多个值如果冲突时,也是有优先级的,而no-store优先级最高。

    缓存校验

    在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时不需要重新发送。缓存校验就是用来解决这些问题的,在http1.1中,主要关注下Last-Modifiedetag这两个字段。

    Last-Modified

    服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-UnModified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不反悔资源;如果不一致,则返回200和修改后的资源,并带上新的时间。

    If-Modified-Since和If-Unmodified-Since的区别是:
    If-Modified-Since:告诉服务器如果时间一致,返回状态码304
    If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412

    etag

    单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理。
    etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。

    If-None-Match和If-Match的区别是:
    If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源
    If-Match:告诉服务器如果不一致,返回状态码412

    iOS webview清除缓存

    当我们的webview缓存到一定的峰值的时候,需要手动的清除一下wenview的缓存,方法如下:

    iOS9.0以前

    找出web缓存的路径,清空该路径

    NSString *libraryDir = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
    NSString *bundleId  =  [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
    
    NSString *webkitFolderInLib = [NSString stringWithFormat:@"%@/WebKit",libraryDir];
    NSString *webKitFolderInCaches = [NSString stringWithFormat:@"%@/Caches/%@/WebKit",libraryDir,bundleId];
    
    NSError *error;
    [[NSFileManager defaultManager] removeItemAtPath:webKitFolderInCaches error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:webkitFolderInLib error:nil];
    
    iOS9.0以后

    webKit除了清除缓存的API

    NSSet *websiteDataTypes = [NSSet setWithArray:@[
                                                     WKWebsiteDataTypeDiskCache,
                                                     WKWebsiteDataTypeOfflineWebApplicationCache,
                                                     WKWebsiteDataTypeMemoryCache,
                                                     WKWebsiteDataTypeLocalStorage,
                                                     WKWebsiteDataTypeCookies,
                                                     WKWebsiteDataTypeSessionStorage,
                                                     WKWebsiteDataTypeIndexedDBDatabases,
                                                     WKWebsiteDataTypeWebSQLDatabases
                                                     ]];
    NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
    //dataTypes: 指定删除的网站数据类型,date: 在此日期之后修改的所有网站数据将被删除,completionHandler: 当网站数据被删除时调用的block。
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
        // 结束回调
    }];
    
    
    /*
     dataTypes包括:
     / * 磁盘缓存。 * /
    WKWebsiteDataTypeDiskCache,
    
    / * 内存中的缓存 。* /
    WKWebsiteDataTypeMemoryCache,
    
    / * HTML离线Web应用程序缓存。 * /
    WKWebsiteDataTypeOfflineWebApplicationCache,
    
    / * Cookies 缓存。 * /
    WKWebsiteDataTypeCookies,
    
    / * HTML会话存储。 * /
    WKWebsiteDataTypeSessionStorage,
    
    / * HTML本地存储。 * /
    WKWebsiteDataTypeLocalStorage 
    
    / * IndexedDB数据库。 * /
    WKWebsiteDataTypeIndexedDBDatabases,
    
    / * WebSQL数据库。 * /
    WKWebsiteDataTypeWebSQLDatabases
    */
    

    觉得有用,请帮忙点亮红心


    Better Late Than Never!
    努力是为了当机会来临时不会错失机会。
    共勉!

    相关文章

      网友评论

        本文标题:iOS web缓存策略以及手动清除缓存

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