一般情况下在UITableView的header或cell中加载webview,需要动态计算webview的内容高度,然后刷新tableview,那么接下来问题的重点就是如何准确的拿到webview的内容高度了
思路1:从WKWebview的加载完成代理方法中着手
代码如下:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result,NSError * _Nullable error) {
//1.获取页面高度,并重新计算webview的高度
//2.缓存页面高度
//3.tableview update
}];
}
但是,很可惜,这里获取的高度有时不精确,于是,采用了另一种方法。
思路2:使用KVO监听webView.scrollView的contentSize
code:
cell的方法
- cell初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIView *superView = self.contentView;
superView.backgroundColor = [UIColor blueColor];
WKWebView *webView = [[WKWebView alloc] initWithFrame:superView.bounds];
webView.scrollView.scrollEnabled = NO;//禁用webView滑动
webView.scrollView.userInteractionEnabled = NO;
//自适应宽高,这句要加
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
// webView.navigationDelegate = self;
_webView = webView;
[superView addSubview:_webView];
//监听webView.scrollView的contentSize属性
[_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
- KVO监听处理
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"contentSize"]) {
__weak typeof(self) weakSelf = self;
//执行js方法"document.body.offsetHeight" ,获取webview内容高度
[_webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
CGFloat contentHeight = [result floatValue];
if (weakSelf.webHeightChangedCallback) {
weakSelf.webHeightChangedCallback(contentHeight);
}
}];
}
}
- 移除kvo监听
- (void)dealloc
{
[_webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
}
- tableview部分
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
return _webHeight;//web高度,全局属性
}
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
WebTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(WebTableViewCell.class)];
if (!cell) {
cell = [[WebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass(WebTableViewCell.class)];
}
__weak typeof(self) weakSelf = self;
cell.webHeightChangedCallback = ^(CGFloat webHeight) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf->_webHeight < webHeight) {//当缓存的高度小于返回的高度时,更新缓存高度,刷新tableview
strongSelf->_webHeight = webHeight;
[weakSelf.tableView beginUpdates];
[weakSelf.tableView endUpdates];
}
};
return cell;
}
return nil;
}
//去除web页底部空白
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { // 判断webView所在的cell是否可见,如果可见就layout
NSArray *cells = self.tableView.visibleCells;
for (UITableViewCell *cell in cells) {
if ([cell isKindOfClass:[WebTableViewCell class]]) {
WebTableViewCell *webCell = (WebTableViewCell *)cell;
[webCell.webView setNeedsLayout];
}
}
}
以上,就实现了tableview加载webview的操作。有不足之处,还请大家指正!
网友评论