WKWebView 网页缓存和刷新

  • 现象描述

由于后台更新了一个网页,但iOS这边显示的还是旧内容。此现象 —— 网页的缓存

  • WKWebView的缓存策略
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
    NSURLRequestUseProtocolCachePolicy = 0, // 默认策略,具体的缓存逻辑和协议的声明有关,如果协议没有声明,不需要每次重新验证cache。
    NSURLRequestReloadIgnoringLocalCacheData = 1, // 忽略本地缓存,直接从后台请求数据
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, //  系统未实现,忽略本地缓存数据、代理和其他中介的缓存,直接从后台请求数据
    NSURLRequestReturnCacheDataElseLoad = 2, // // 优先从本地拿数据,且忽略请求生命时长和过期时间。但是如果没有本地cache,则请求源数据
    NSURLRequestReturnCacheDataDontLoad = 3,  //只从本地拿数据
    NSURLRequestReloadRevalidatingCacheData = 5, //  未实现 从原始地址确认缓存数据的合法性后,缓存数据就可以使用,否则从原始地址加载。
};

这里我们需要注意的是 NSURLRequestReloadIgnoringLocalCacheData 和 NSURLRequestReturnCacheDataElseLoad
NSURLRequestReloadIgnoringLocalCacheData忽略缓存,直接取网络。
NSURLRequestReturnCacheDataElseLoad先读取缓存,没有缓存则取网络。

  • 获取网络最新数据

1、使用 NSURLRequestReloadIgnoringLocalCacheData 来实时加载网页

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.urlString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20];
[_webView loadRequest:request];

2、通过 NSHTTPURLResponse 中的 Last-Modified 或者 Etags 来判断当前html是否是最新的网页(此方法没有亲测)

  • Last-Modified

表示文件的最后修改时间,例如"Fri, 26 Oct 2018 03:17:23 GMT",当请求 html 时,我们会向服务器发送 If-Modified-Since 报头,查看文件是否被修改,如果没有被修改,则 HTTP 返回303状态码,如果会修改了返回200。

  • Etags

客户端通过 If-None-Match 这个条件判断请求来验证资源是否修改。服务器判断发送过来的 Etag 和计算出来的 Etag 匹配,因此 If-None-Match 为False,不返回200,返回304,客户端继续使用本地缓存。

具体可以看这篇HTTP缓存控制小结

先查看打印

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]
                                                               cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                           timeoutInterval:20];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSLog(@"httpResponse == %@", httpResponse);
        }] resume];

可以看到

httpResponse ==  { URL: ---} { 
Status Code: 304, 
Headers {
    Date =     (
        "Sat, 27 Oct 2018 01:19:36 GMT"
    );
    Etag =     (
        "\"5bb086b4-2bd\""
    );
    "Last-Modified" =     (
        "Sun, 30 Sep 2018 08:17:56 GMT"
    );
    Server =     (
        Tengine
    );
} }

想要的参数都在里面。


具体实现

_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, WY_ScreenWidth, WY_ScreenHeight - WY_NavBar_H + WY_SAFE_TOP) configuration:configuration];
        _webView.navigationDelegate = self;
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]
                                                               cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                           timeoutInterval:20];
        NSDictionary *cachedHeaders = [[NSUserDefaults standardUserDefaults] objectForKey:self.urlString];
        //设置request headers (带上上次的请求头下面两参数一种就可以,也可以两个都带上)
        if (cachedHeaders) {
            NSString *etag = [cachedHeaders objectForKey:@"Etag"];
            if (etag) {
                [request setValue:etag forHTTPHeaderField:@"If-None-Match"];
            }
            NSString *lastModified = [cachedHeaders objectForKey:@"Last-Modified"];
            if (lastModified) {
                [request setValue:lastModified forHTTPHeaderField:@"If-Modified-Since"];
            }
        }
        [_webView loadRequest:request];
        
        [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSLog(@"httpResponse == %@", httpResponse);
// 根据statusCode设置缓存策略
            if (httpResponse.statusCode == 304 || httpResponse.statusCode == 0) {
                [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
            } else {
                [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
// 保存当前的NSHTTPURLResponse
            [WY_UserDefaults setObject:httpResponse.allHeaderFields forKey:self.urlString];
            }
// 重新刷新
            dispatch_async(dispatch_get_main_queue(), ^{
                [_webView reload];
            });
        }] resume];

这样就达到了缓存的目的。

 

你可能感兴趣的:(iOS)