iOS开发漫话WKWebView之动态获取网页高度

        最近在项目开发中遇到一个需求,一篇文章顶部的分析师信息以及底部的评论和回复以及文本框信息采用原生展示,中间的主体内容采用Vue框架做的H5展示。这里里面唯一的遇到的问题就是动态计算H5网页的高度,使得页面整体如一,不会有手势冲突。整体效果如下图:

经过搜索资料整理,基本有两种思路,一是通过在didFinish里面注入Js脚本获取页面的scrollHeight,二是通过iOS的KVO模式监听contentSize的值(也有注入Js来监听的,操作有难度)。在不同网页和不同系统中测试,KVO模式能实现需求而且高度准确无误。现将主要参考代码列出如下:

1、定义WKWebView并添加contentSize监听

import WebKit

private let content_size_key = "contentSize"
private let ScreenWidth: CGFloat = UIScreen.main.bounds.size.width

private lazy var wkWebView:WKWebView = {[unowned self] in
        let _wk = WKWebView.init(frame: .zero)

        //监听
        _wk.scrollView.addObserver(self,
                                  forKeyPath: content_size_key,
                                  options: NSKeyValueObservingOptions.new, context: nil)
        
        return _wk
}()

2、实现监听存储高度值

//MARK: - KVO 监听
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        //根据内容的高重置webView视图的高度
        guard let webCGSize = change?[NSKeyValueChangeKey.newKey] as? CGSize  else {
            return
        }

        //[S] 此处代码是处理在iOS13.6中 contentSize 高度偏高产生大量空白的
        var _h:CGFloat = webCGSize.height
        if webCGSize.width > ScreenWidth {
            _h = (ScreenWidth / webCGSize.width) * _h
        }
        //[E]
        
        if !self.arrHeights.contains(_h) {
            self.arrHeights.append(_h)
        }
    }

3、更新UI

private lazy var arrHeights = [CGFloat]() {
   didSet{
       if self.arrHeights.count > 0 {
           if let _h = self.arrHeights.sorted(by: { return $0 > $1 }).first {
               self.updateWebViewFor(Height: _h)
            }
        }
   }
}

/// 更新高度(也有通过约束来更新,殊途同归)
/// - Parameter h: CGFloat
func updateWebViewFor(Height h:CGFloat){
        
    DispatchQueue.main.async {
          var rect = self.wkWebView.frame
          rect.size.height = h
          self.wkWebView.frame = rect
            
          //headView是UITableView 的 tableHeaderView
          //wkWebView 是headView的一部分
          rect = self.headView.frame
          rect.size.height = SpecialColumnMainView.section_head_height2 + 30 + h
          self.headView.frame = rect
            
          self.listTableView.reloadData()
    }
}

4、销毁移除监听

    deinit {
        self.wkWebview.scrollView.removeObserver(self, forKeyPath: content_size_key, context: nil)
    }

补充,网络上有大量KVO监听contentSize 高度不准确的问题,本文中已解决,详见文中注释

准确获取H5网页的高度有个前提,就是防止网页高度塌陷,具体请参考:https://blog.csdn.net/weixin_39851592/article/details/83622716

本文结束,OC版的可照此操作,有问题可以留言咨询。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追夢秋陽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值