【问题标题】:UIWebView delegate and asynchronous loadingUIWebView 委托和异步加载
【发布时间】:2023-04-26 14:15:01
【问题描述】:

我正在尝试根据其内容自动设置 UIWebView 大小,虽然这很容易提取正在加载的内容,但给我带来了一些麻烦

我做了一个简单的app来测试这个行为,代码如下。

func webViewDidFinishLoad(_ webView: UIWebView)
{
    print(webView.scrollView.contentSize.height)
    webViewHeight.constant = webView.scrollView.contentSize.height
    self.view.setNeedsUpdateConstraints()
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
}

override func viewDidLoad() {
    super.viewDidLoad()

    webView.loadHTMLString(htmlstring, baseURL: nil)
    webView.delegate = self
    // Do any additional setup after loading the view, typically from a nib.
}

html字符串如下

<blockquote class=\"instagram-media\" data-instgrm-captioned data-instgrm-version=\"7\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\"><div style=\"padding:8px;\"> <div style=\" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;\"> <div style=\"background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;\"></div></div> <p style=\" margin:8px 0 0 0; padding:0 4px;\"> <a href=https://www.instagram.com/p/BLpA4TKAdPr/ style= \" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;\" target=\"_blank\"></p></div></blockquote> <script async defer src=\"http://platform.instagram.com/en_US/embeds.js\"></script>

(这是一个 Instagram 嵌入)

现在的问题是,如果您尝试运行此 webViewDidFinishLoad 将被触发多次,这当然是意料之中的,但即使在它完成后,结果高度仍然不正确,因为嵌入将被切断

我认为这是因为图片稍后通过 AJAX 或类似方式加载,这意味着此时高度没有考虑到图片(甚至可能没有考虑到标题?)

我的问题是对于这种我无法更改的特定类型的内容,我如何判断该过程何时真正结束并为 WebView 获得正确的大小?

【问题讨论】:

    标签: ios uiwebview


    【解决方案1】:

    我们在 Brave.app 中观察滚动视图内容大小的变化:

    webView.scrollView.addObserver(self, forKeyPath: "contentSize", options: .New, context: nil)
    

    和接收者:

     override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "contentSize"  {
        // should give you correct height
            print(webview.scrollView?.contentSize.height)
        }
    }
    

    以下是此代码在我们的应用程序中的位置: https://github.com/brave/browser-ios/blob/d9b5500de863625fc4e7f1ade8f6c428842f3063/brave/src/frontend/BraveScrollController.swift#L195

    【讨论】:

    • 谢谢,我会尽快尝试。这适用于多个 UIWebViews 吗?不幸的是,客户希望将这些嵌入放置在可能有数百个实例的表格视图中(我知道这很糟糕)
    • 是的,我们的应用程序中有多个 web 视图,不确定具体在哪里您认为可能存在问题。关键路径观察具有指示发送对象的设施,例如:webView1.scrollView.addObserver(...); webView2.scrollView.addObserver(...) 和在 observeValueForKeyPath(..) 中:if object == webView1 { dosomething }