iOS开发 | UIWebView&WKWebView高

作者: 无夜之星辰 | 来源:发表于2017-02-11 23:48 被阅读3207次
少女时代-林允儿

需求还原:

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

上部分是普通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<NSKeyValueChangeKey,id> *)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<NSKeyValueChangeKey,id> *)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;
    });
}

相关文章

网友评论

  • edb493d9a752:第一次加载的时候 走了监听 但是更新url的时候不走监听 怎么办
  • manofit:最近用WKwebview,出现底部空白,甩给h5那边了,老夫已经无能为力了
    无夜之星辰:@manofit 恩恩,那就好
    manofit:@无夜之星辰 这个我倒没注意,不过现在那边已经解决了,其实就是那边高度没有自适应
    无夜之星辰:你用WKWebView后,是不是字体变小了?
  • 51aa90fc67ff:看了这么多方法 ,这个最有效!:joy: :joy:
  • 专心致志的程序员:妹夫,不错学习了,待会去试试:smile:
  • a632073b5a6a:大神,有没得demo啊,最近弄这个玩意弄了两天了
    无夜之星辰:@lyq226809 你用的UIWebView还是WKWebView?如果是WKWebView这几种方法都不能保证一定有效,我也没找到有效的方法。UIWebView直接观察scroll view 的contentSize就可以了
  • 伦敦乡下的小作家:妹夫,写得不错,项目正好有类似的需求
    无夜之星辰:妹儿我都没看到:sleepy:
  • 春暖花已开:妹夫,写得不错,项目正好有类似的需求
    无夜之星辰:@人民重重 在网上找了很久,没找到合适的,后面我灵光一闪,想到了kvo,完美解决问题。还有,你都还没把你妹介绍给我:smirk:

本文标题:iOS开发 | UIWebView&WKWebView高

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