iOS开发 | UIWebView&WKWebView高度自适应内容的正确姿势以及持续自适应

iOS开发 | UIWebView&WKWebView高度自适应内容的正确姿势以及持续自适应_第1张图片
少女时代-林允儿

需求还原:

如图所示:
整个页面分为上下两部分:上部分是普通的view,下部分是一个webview,加载H5文本。需求是这两部分要同时滚动。

iOS开发 | UIWebView&WKWebView高度自适应内容的正确姿势以及持续自适应_第2张图片
上部分是普通view下部分是webview.png

思路

把上下两部分放在一个scrollView上,设置webview不可滚动并且让webview高度自适应内容(webView.height = webView.scrollView.contentSize.height),再调整scrollView的contentSize。

实现方法

在webview的代理方法webViewDidFinishLoad:中做相应处理即可:


- (void)webViewDidFinishLoad:(UIWebView *)webView{
    // webView加载完成,让webView高度自适应内容
    self.contentWebView.height = self.contentWebView.scrollView.contentSize.height;
    self.contentScrollView.contentSize = CGSizeMake(screenWidth, self.contentWebView.maxY);
}

存在的问题

没过多久,测试妹纸就反馈有时webview只显示了部分内容。我就纳闷了,我的思路和代码都是完美无bug的,不应该有问题啊但是后面测试妹纸不停的向我反馈这个问题,我知道,肯定是自己的代码有问题了。把代码反复看了几遍,最终定位到webViewDidFinishLoad :这个方法上。于是上网查询,终于知道了原因:
我想当然的认为webViewDidFinishLoad :回调之时就是webview加载完成之日(有多少人被坑过)。实际上并不是,这里就不做过多讨论了,详情自己上网查询(网页重定向)。只需要记住:webViewDidFinishLoad :回调的时候并不能说明webview加载完成

解决问题

知道问题所在后解决问题就简单了:需要找准webview加载完成的那个点。结合网上前辈提供的方法,我给UIWebView写了一个category,用来判断webview是不是真正的完成了加载。代码如下:

/** 判断webView是否完全加载完数据 */
- (BOOL)isFinishLoading{
    NSString *readyState = [self stringByEvaluatingJavaScriptFromString:@"document.readyState"];
    BOOL complete = [readyState isEqualToString:@"complete"];
    if (complete && !self.isLoading) {
        return YES;
    }else{
        return NO;
    }
}

这就在原来的基础上多了一个判断:

- (void)webViewDidFinishLoad:(UIWebView *)webView{
    // webView加载完成,让webView高度自适应内容
    if ([webView isFinishLoading] == YES) {
        self.contentWebView.height = self.contentWebView.scrollView.contentSize.height;
        self.contentScrollView.contentSize = CGSizeMake(screenWidth, self.contentWebView.maxY);
    }
}

这样,webview高度自适应内容就完成了。

优化

虽然功能是完成了,但是却不怎么完美:我们初始化webview的时候会给webview设置一个frame,如果webview的height设置低了,加载数据期间将只能显示部分内容;如果webview高度设置太大,加载数据期间下方又是一片空白。如果能动态持续的改变webview的高度,那这个问题也就解决了。方法就是:实时监听webview的scrollView的contentSize的变化,然后调整webview的高度。代码如下:

    // webview高度自适应内容
    [RACObserve(self.contentWebView.scrollView, contentSize) subscribeNext:^(id x) {
        self.contentWebView.height = self.contentWebView.scrollView.contentSize.height;
        self.contentScrollView.contentSize = CGSizeMake(screenWidth, self.contentWebView.maxY);
    }];

这是最简单同时也是最完美的实现方法(用这个方法就不需要再在webview的代理方法里做处理了)。什么你没用RAC?好吧那你就用传统的KVO咯。建议没学RAC的去了解一下,有时候对于简化代码还是很有帮助的。

至此,UIWebView高度自适应内容以及持续自适应就完美实现了。讲了这么多其实核心就是监听webView.scrollView.contentSize的变化然后调整webView的高度

WKWebView处理方式一样

使用KVO:

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    self.webView.height = self.webView.scrollView.contentSize.height;
}

使用WKWebView时你可能会遇到的问题

1. 字体相比UIWebView更小了

解决方法:https://stackoverflow.com/questions/45998220/the-font-looks-like-smaller-in-wkwebview-than-in-uiwebview/46000849#46000849

2.底部大片空白

解决方法:稍微延迟一下

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.webView.height = self.webView.scrollView.contentSize.height;
    });
}

你可能感兴趣的:(iOS开发 | UIWebView&WKWebView高度自适应内容的正确姿势以及持续自适应)