iOS Calculate correct WKWebview height for html string with embeded tweet
我正在使用wkwebview使用loadHTMLString方法加载给定的HTML字符串。在wkwebview didFinishNavigation之后,我通过评估javascript" document.height"将wkwebview的高度更新为内容高度。
这适用于纯HTML字符串。
但对于带有嵌入推文高度的html字符串,计算会出错。
这是tweet内容
1 2 3 4 5 6 7 8 9 10 | </p> <blockquote class="twitter-tweet"> <p lang="fr" dir="ltr">Union Cabinet approves civil aviation policy.</p> Press Trust of India (@PTI_News) June 15, 2016</blockquote> <p> 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")); |
因此,在webview完全加载twitter提要之后,我们不会在wkwebviewdelegate方法中获得回调。
在这种情况下,最好的解决方案是与观察者一起监听" contentSize"上的更改。
为此,您将需要以下两个变量:
1 2 3 4 5 6 7 8 9 10 11 12 | 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方法可以忽略,但是在我看来,没有它就无法很好地更新视图的大小。而且我在底部有一个空格。
开始观察和监听更改的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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的框架,这将开始更新高度。
1 2 3 4 5 6 7 8 9 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { indicatorLoading?.stopAnimating() webViewHeight = webView.scrollView.contentSize.height webView.isHidden = false if (!observing) { startObservingHeight() } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //Add some Scheme tag in your HTML string. let urlwithScheme = 'widget.twitter.myapp://url’ let strTwitter =" twttr.ready(function(e){ twttr.events.bind('rendered', function (event) { window.location = \\(urlwithScheme); } ); })" 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) } |