前言
需要显示一个资讯详情页面,涉及到webView
和自定义控件的结合,页面上半部分是webView
,下面是一个tableView
,webView
必须显示完整的网页信息,这时候就需要计算出webView
的高度。
方法
网上介绍的方法很多,大概分为两种。
方法1:在webView
的代理中去获取webView
的高度
//WKWebView
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
if (self.hud) {
[self.hud hideAnimated:YES];
}
[webView evaluateJavaScript:@"document.body.scrollHeight"
completionHandler:^(id result, NSError *_Nullable error) {
[self.webView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.equalTo([result floatValue]);
}];
self.tableView.tableHeaderView = self.headerView;
}];
}
方法2:通过KVO
监听webView
的高度,然后更新高度。
//WKWebView
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
//监听高度变化
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"contentSize"]) {
}
}
问题
用上面方法1
和方法2
方法监听高度,然后更新高度偶尔会发现高度不准。因为webView
中包含图片等资源它们加载过程中需要一定时间,只有当它们完全加载完成以后,获取的高度才是真正的高度。
解决办法
方法1:通过代理
和KVO
监听webView
高度变化
-
监听
webView
的高度变化。//WKWebView [self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil]; [self.webView makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(timeLab.mas_bottom).offset(10); make.left.right.equalTo(titleLab); make.height.equalTo(100); }]; //代理中更新contentHeight变量变化 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ if (self.hud) { [self.hud hideAnimated:YES]; } [webView evaluateJavaScript:@"document.body.scrollHeight" completionHandler:^(id result, NSError *_Nullable error) { [self.webView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.equalTo([result floatValue]); }]; self.tableView.tableHeaderView = self.headerView; }]; } //KVO监听webView高度变化从而刷新UI - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"contentSize"]) { CGFloat height = self.webView.scrollView.contentSize.height; NSLog(@"-----------height= %.1f",height); [self.webView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.equalTo(height); }]; self.tableView.tableHeaderView = self.headerView; } } //移除KVO监听 -(void)dealloc{ [self.webView.scrollView removeObserver:self forKeyPath:@"contentSize"]; }
通过上述方法基本可以实现功能。
方法2:通过和H5
进行JS
交互从而实现监听
H5
那边一定要在文字跟图片都加载完成再去获取高度,因为图片是异步加载的,否则获取到的高度不准。在H5完成加载内容后通过JS
告诉App
然后App
实现刷新
//(1)进行配置控制器---跟H5交互用
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
//实例化对象
configuration.userContentController = [WKUserContentController new];
WKWebView * webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 10)];
//(2)与JS交互的注册,JS调用OC方法--注册前先z初始化上面方法
[webView.configuration.userContentController addScriptMessageHandler:self name:@"getWkWebViewHeight"];
//(3)加载url
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.urlString]]];
//(4)HTML内容从后台请求完成后传给H5--js,等待H5加载完页面给iOS回调高度【注意:H5那边一定要在图片也加载完后才返回高度,不然返回的高度不准】
NSString * HtmlStr = @"HTML内容
";
NSDictionary *dicData = @{@"content": HtmlStr};
//字典转JSON
NSString * jsonStr = [NSDictionary dictionaryToJson:dicData];
NSString *js = [NSString stringWithFormat:@"window.dataInfo = %@", jsonStr];
WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:(WKUserScriptInjectionTimeAtDocumentStart) forMainFrameOnly:YES];
[[self configuration].userContentController addUserScript:script];
//得到js传输回来的数据
//WKScriptMessageHandler协议方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
//code
// NSDictionary *dictData = [NSDictionary jsonToDictionaryWithJsonString:message.body];
if ([message.name isEqualToString:@"getWkWebViewHeight"]) {
NSLog(@"获取新闻高度:%@",message.body);
if ([self.typeString isEqual:@"新闻详情"]) {
NSString * strHeight = [NSString stringWithFormat:@"%@",message.body];
CGFloat heightWeb = [strHeight doubleValue];//得到网页高度
//网页高度回调
if (self.WebviewHeight) {
self.WebviewHeight(heightWeb);
}
}
}
}