iOS为带有嵌入推文的html字符串计算正确的WKWebview高度

Posted

技术标签:

【中文标题】iOS为带有嵌入推文的html字符串计算正确的WKWebview高度【英文标题】:iOS Calculate correct WKWebview height for html string with embeded tweet 【发布时间】:2016-06-15 10:29:47 【问题描述】:

我正在使用 wkwebview 使用 loadhtmlString 方法加载给定的 HTML 字符串。在 wkwebview didFinishNavigation 之后,我通过评估 javascript“document.height”将 wkwebview 的高度更新为内容高度。 这适用于纯 html 字符串。

但是对于嵌入推文高度计算的 html 字符串会出错。 这是推文内容

</p>
<blockquote class="twitter-tweet">
<p lang="fr" dir="ltr">Union Cabinet approves civil aviation policy.</p>&mdash; Press Trust of India (@PTI_News) 
<a href="https://twitter.com/PTI_News/status/742990663495647232">June 15, 2016</a></blockquote>
<p>
<script>window.twttr = (function(d, s, id) 
var js, fjs = d.getElementsByTagName(s)[0],t = window.twttr || ;if (d.getElementById(id)) return t;js = d.createElement(s);js.id = id;
js.src = "https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js, fjs);t._e = [];
t.ready = function(f) 
t._e.push(f);;return t;(document, "script", "twitter-wjs"));</script>

所以在 webview 完全加载 twitter feed 之后,我们不会在 wkwebviewdelegate 方法中得到回调。

【问题讨论】:

嗨,这个问题你解决了吗? 是的,我解决了这个问题。 怎么样,我也有同样的问题。谢谢, 请检查我的答案。 【参考方案1】:

在这种情况下,最好的解决方案是通过观察者监听“contentSize”的变化。

为此,您需要以下 2 个变量:

var observing = false

internal var webViewHeight: CGFloat = 0 
    didSet 
        guard let webViewHeightConstraint = self.heightConstraint else  return 
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) 
            webViewHeightConstraint.constant = self.webViewHeight
            self.view.layoutSubviews()
            self.delegate?.view.layoutSubviews()
        
    

可以忽略 asyncAfter 方法,但在我的情况下,没有它,视图的大小不会很好地更新。我在底部得到了一个空白区域。

开始观察和监听变化的方法如下:

func startObservingHeight() 
    let options = NSKeyValueObservingOptions([.new])
    webView?.scrollView.addObserver(self, forKeyPath: "contentSize", options: options, context: nil)
    observing = true


func stopObservingHeight() 
    webView?.scrollView.removeObserver(self, forKeyPath: "contentSize", context: nil)
    observing = false


override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
    guard let keyPath = keyPath else 
        super.observeValue(forKeyPath: nil, of: object, change: change, context: context)
        return
    
    switch (keyPath, context) 
    case("contentSize", nil):
        webViewHeight = (webView?.scrollView.contentSize.height)!
    default:
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    

如您所见,变量 webViewHeight 将在收到新值时更新。

在你的 didFinish 导航方法中,你应该开始“监听”观察者调用之前的方法 startObservingHeight。这将在 twitter 的框架完成后开始更新高度。

func webView(_ webView: WKWebView,
             didFinish navigation: WKNavigation!) 
    indicatorLoading?.stopAnimating()
    webViewHeight = webView.scrollView.contentSize.height
    webView.isHidden = false
    if (!observing) 
        startObservingHeight()
    

【讨论】:

非常爱你,当你在 wkwebview 中嵌入异步时,这是最好的答案【参考方案2】:
    //Add some Scheme tag in your HTML string. 

    let urlwithScheme = 'widget.twitter.myapp://url’

    let strTwitter = "<script> twttr.ready(function(e) twttr.events.bind('rendered', function (event)  window.location = \(urlwithScheme);  ); ) </script>"
    let strHTML = "<!DOCTYPE html><html>\(strTwitter)</html>"



    // After load HTML check url scheme, if it belongs to twitter rendered action or not

    @available(ios 8.0, *)


    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
        // If twitter feed finished renderin
        if(navigationAction.request.url?.scheme == "widget.twitter.myapp")
            // Don’t update frame here
            decisionHandler(.cancel)
        

        decisionHandler(.allow)

【讨论】:

以上是关于iOS为带有嵌入推文的html字符串计算正确的WKWebview高度的主要内容,如果未能解决你的问题,请参考以下文章

更改嵌入推文的最大宽度

如何覆盖嵌入推文的样式表

特定推文的Twitter链接的URL

如何在 React 中更改嵌入推文的宽度?

如何将推特链接转换为嵌入式推文?

如何使用 tweepy 而不是带有链接的推文的一部分来获取整个推文