美文网首页
解决web view白屏问题

解决web view白屏问题

作者: huicuihui | 来源:发表于2018-03-20 16:57 被阅读401次
    问题描述:

    点击文章列表进入文章详情,会有几秒显示空白页面,之后才是加载请求数据。加载请求数据显示加载动画,这段时间是可以接受的。主要矛盾是解决加载动画显示之前的白屏问题。

    解决方法:

    把页面文件保存到本地, 加载的时候,加载本地的,因为文章详情里面html文件代码都一样,框架都是那样的。只要后台那边不改代码,一般情况下都不变,所以把那个文件存到本地,以后都读本地读文件即可。不用去请求服务器,不再受服务器响应速度影响。

    代码如下:

    在加载webView的时候改为下面方法:
    - (void)loadHtml {
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
       NSString *path = [cachesPath stringByAppendingString:[NSString stringWithFormat:@"/Caches/%lu.html",[@"huancunwenzhang" hash]]];
       NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    
    //有缓存
        if (!(htmlString == nil || [htmlString isEqualToString:@""])) {
            [_wkWebview loadHTMLString:htmlString baseURL:[NSURL URLWithString:self.urlString]];
        }
    //没缓存
     else {
            NSURL *url = [NSURL URLWithString:self.urlString];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            [_wkWebview loadRequest:request];
    //没有缓存需要缓存
            [self writeToCache];
        }
    }
    

    注还有优化的地方:
    可以把上面htmlString读取到内存中,常驻内存中,app运行时使用同一个。减少一点读取文件的时间。

    将html文件保存到本地:
    - (void)writeToCache {
    //@"https://app.ningmengyun.com/news/newsDetail.html" 是html文件路径,后面不需要加某篇文章id等参数。
        NSString *htmlResponseStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://app.ningmengyun.com/news/newsDetail.html"] encoding:NSUTF8StringEncoding error:nil];
    
        //创建文件管理器
        NSFileManager *fileManager = [NSFileManager defaultManager];
        //获取document路径
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        [fileManager createDirectoryAtPath:[cachesPath stringByAppendingString:@"/Caches"] withIntermediateDirectories:YES attributes:nil error:nil];
        //写入路径
        NSString *path = [cachesPath stringByAppendingString:[NSString stringWithFormat:@"/Caches/%lu.html",[@"huancunwenzhang" hash]]];
        [htmlResponseStr writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
    }
    

    设置html文件过期时间

    在请求数据的时候,header中有一个过期时间。

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
    

    在上面方法中打印navigationResponse可以看到header。

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
    {
        NSString *cacheControl = [(NSHTTPURLResponse*)navigationResponse.response allHeaderFields][@"Cache-Control"]; // max-age, must-revalidate, no-cache
        NSArray *cacheControlEntities = [cacheControl componentsSeparatedByString:@","];
    
        for(NSString *substring in cacheControlEntities) {
            
            if([substring rangeOfString:@"max-age"].location != NSNotFound) {
                
                // do some processing to calculate expiresOn
                NSString *maxAge = nil;
                NSArray *array = [substring componentsSeparatedByString:@"="];
                if([array count] > 1)
                    maxAge = array[1];
                
               NSDate * expiresOnDate = [[NSDate date] dateByAddingTimeInterval:[maxAge intValue]];
            }
        }
        decisionHandler(WKNavigationResponsePolicyAllow);
    }
    

    问题:
    当后台那边对html文件进行了修改之后,app内html文件还没到过期时间,那么就会出请求不到数据等等问题。
    解决方法:
    可以只请求该url地址的header头, 请求的数据也不多,响应相应的比其他的请求快些。
    对应的代码如下:

    /**
     请求header,获取头部的信息。
     */
    - (void)requestWebViewHeader:(void (^)(BOOL isLoadCache))block {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        [manager HEAD:self.urlString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task) {
            NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
            if ([[userDefaults objectForKey:kHtml_lastModified] isEqual:[(NSHTTPURLResponse*)task.response allHeaderFields][@"Last-Modified"]]) {
                block(YES);
            } else {
                block(NO);
                [[NSUserDefaults standardUserDefaults] setObject:[(NSHTTPURLResponse*)task.response allHeaderFields][@"Last-Modified"] forKey:kHtml_lastModified];
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%@",error);
            block(YES);
        }];
    }
    
    控制台输出:
    (lldb) po task.response
    <NSHTTPURLResponse: 0x60400082f480> { URL: http://apptest.ningmengyun.com/news/newsDetail.html?ArticleID=1159&withNavigationBar=true } { Status Code: 200, Headers {
        "Accept-Ranges" =     (
            bytes
        );
        "Content-Encoding" =     (
            gzip
        );
        "Content-Length" =     (
            1353
        );
        "Content-Type" =     (
            "text/html"
        );
        Date =     (
            "Mon, 23 Apr 2018 04:06:18 GMT"
        );
        Etag =     (
            "\"809d9cf9cbd7d31:0\""
        );
        "Last-Modified" =     (
            "Thu, 19 Apr 2018 10:48:39 GMT"
        );
        Server =     (
            "Microsoft-IIS/7.5"
        );
        Vary =     (
            "Accept-Encoding"
        );
        "X-Powered-By" =     (
            "ASP.NET"
        );
    } }
    
    (lldb) po lastModified
    Thu, 19 Apr 2018 10:48:39 GMT
    
    (lldb) 
    

    关于url的问题:

    点击每条文章,传入的url为https://app.ningmengyun.com/news/newsDetail.html?ArticleID=1034,其中的ArticleID为每条文章的id,但是缓存html和请求header头的时候不需要整个url,只需要前面的地址即可。参数都不需要。即:https://app.ningmengyun.com/news/newsDetail.html

    请求头的参考:
    https://blog.csdn.net/u013583789/article/details/52129316

    相关文章

      网友评论

          本文标题:解决web view白屏问题

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