iOS WKWebView 在嵌入推文时计算高度不正确
iOS WKWebView improperly calculating height when there is embedded tweet
我的应用程序使用 WKWebView 来呈现 html 字符串。 WkWebView 嵌入在 scrollView 中,因为我有几个其他元素(例如按钮、tableViews)。因此,我需要计算 WkWebvView 内容的大小,为此我使用 evaluateJavaScript(“document.body.scrollHeight”, completionHandler: 方法。
每当我在 html 字符串中嵌入推文时,内容高度计算错误并且我的 webview 削减了它的一部分高度。
嵌入推文的 html 字符串的一部分如下所示:
<blockquote class=\"twitter-tweet\" data-lang=\"en\"><p><a
href=\"https://twitter.com/hashtag/SYRIA?src=hash\">#SYRIA</a> Admiral Essen frigate launched <a href=\"https://twitter.com/hashtag/Kalibr?src=hash\">#Kalibr</a> cruise missiles against ISIS objects near Deir ez-Zor <a href=\"https://BLABLA*\">pic.twitter.com/azHAIii07g</a></p><p>— Минобороны России (@mod_russia) <a href=\"https://twitter.com/mod_russia/status/905007557554700288\">September 5, 2017</a></p></blockquote><p><script src=\"https://platform.twitter.com/widgets.js\"></script>
(BLABLA* 实际上是 t.co/azHAIii07g,由于 Whosebug 规则我不得不更换它)
此推特代码中是否缺少某些内容,或者我应该在 webview 方法中设置一些内容?
我尝试从这个 post 实施解决方案:iOS Calculate correct WKWebview height for html string with embeded tweet 但没有成功,或者至少我可以找到答案。
有什么建议吗??
更新:
我砍了一点,发现了可怕的解决方法,但这是解决问题所在的一个很好的线索。
这是我用来计算高度的完整函数:
`func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.webViewx.evaluateJavaScript("document.readyState", completionHandler: {
[weak self] (complete, error) in
if complete != nil { self?.webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: {
[weak self] (height, error) in
})
}`
如果我输入:
`DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1, execute: {
self?.webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: {
[weak self] (height, error) in
print("HEIGHT AFTER 1 sec", height)
})
})`
我在 1 秒后得到正确的高度。现在,在正确的时间之后获取高度更新的方法是什么。
此外,请注意,如果我嵌入了 facebook 或 instagram post,一切都会正常运行,并且会正确计算 webview 高度。
在 Whosebug 上的几篇帖子(尤其是:Twitter Uncaught TypeError: undefined is not a function)和我的 Web 开发同事的帮助下,我设法找到了解决此问题的方法。
基本上,如果 webview 需要加载的 html 字符串中有嵌入的推文,则想法是将脚本添加到 webview 配置。之后我们应该实现 userContentController didReceive 消息函数,我们应该在其中评估 webview 的高度。
这是 webview.loadHtmlString 方法之前的代码:
if htmlString.contains("platform.twitter.com/widgets.js") {
let twitterJS: String = "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\"));twttr.ready(function (twttr) {twttr.events.bind('loaded', function (event) {window.webkit.messageHandlers.callbackHandler.postMessage('TWEET');});});"
let userScript = WKUserScript(source: twitterJS, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webViewx.configuration.userContentController.removeAllUserScripts()
webViewx.configuration.userContentController.addUserScript(userScript)
webViewx.configuration.userContentController.add(self, name: "callbackHandler")
}
首先检查 html 字符串是否包含嵌入推文的子字符串。
分配给 twitterJS 的脚本是我们从 twitter 网页上得到的。
从某种意义上说,最后一行很重要,它为我们的脚本命名。
实际身高评价是这样的:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "callbackHandler" {
print(message.body)
webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: { (height, error) in
if let error = error {
print(error.localizedDescription)
return
}
if let height = height as? CGFloat{
if height > self.kontejnerHeight.constant {
self.kontejnerHeight.constant = height
}
}
})
}
}
希望这对其他人也有帮助。
我的应用程序使用 WKWebView 来呈现 html 字符串。 WkWebView 嵌入在 scrollView 中,因为我有几个其他元素(例如按钮、tableViews)。因此,我需要计算 WkWebvView 内容的大小,为此我使用 evaluateJavaScript(“document.body.scrollHeight”, completionHandler: 方法。 每当我在 html 字符串中嵌入推文时,内容高度计算错误并且我的 webview 削减了它的一部分高度。
嵌入推文的 html 字符串的一部分如下所示:
<blockquote class=\"twitter-tweet\" data-lang=\"en\"><p><a
href=\"https://twitter.com/hashtag/SYRIA?src=hash\">#SYRIA</a> Admiral Essen frigate launched <a href=\"https://twitter.com/hashtag/Kalibr?src=hash\">#Kalibr</a> cruise missiles against ISIS objects near Deir ez-Zor <a href=\"https://BLABLA*\">pic.twitter.com/azHAIii07g</a></p><p>— Минобороны России (@mod_russia) <a href=\"https://twitter.com/mod_russia/status/905007557554700288\">September 5, 2017</a></p></blockquote><p><script src=\"https://platform.twitter.com/widgets.js\"></script>
(BLABLA* 实际上是 t.co/azHAIii07g,由于 Whosebug 规则我不得不更换它)
此推特代码中是否缺少某些内容,或者我应该在 webview 方法中设置一些内容?
我尝试从这个 post 实施解决方案:iOS Calculate correct WKWebview height for html string with embeded tweet 但没有成功,或者至少我可以找到答案。
有什么建议吗??
更新: 我砍了一点,发现了可怕的解决方法,但这是解决问题所在的一个很好的线索。 这是我用来计算高度的完整函数:
`func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.webViewx.evaluateJavaScript("document.readyState", completionHandler: {
[weak self] (complete, error) in
if complete != nil { self?.webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: {
[weak self] (height, error) in
})
}`
如果我输入:
`DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1, execute: {
self?.webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: {
[weak self] (height, error) in
print("HEIGHT AFTER 1 sec", height)
})
})`
我在 1 秒后得到正确的高度。现在,在正确的时间之后获取高度更新的方法是什么。
此外,请注意,如果我嵌入了 facebook 或 instagram post,一切都会正常运行,并且会正确计算 webview 高度。
在 Whosebug 上的几篇帖子(尤其是:Twitter Uncaught TypeError: undefined is not a function)和我的 Web 开发同事的帮助下,我设法找到了解决此问题的方法。 基本上,如果 webview 需要加载的 html 字符串中有嵌入的推文,则想法是将脚本添加到 webview 配置。之后我们应该实现 userContentController didReceive 消息函数,我们应该在其中评估 webview 的高度。
这是 webview.loadHtmlString 方法之前的代码:
if htmlString.contains("platform.twitter.com/widgets.js") {
let twitterJS: String = "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\"));twttr.ready(function (twttr) {twttr.events.bind('loaded', function (event) {window.webkit.messageHandlers.callbackHandler.postMessage('TWEET');});});"
let userScript = WKUserScript(source: twitterJS, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webViewx.configuration.userContentController.removeAllUserScripts()
webViewx.configuration.userContentController.addUserScript(userScript)
webViewx.configuration.userContentController.add(self, name: "callbackHandler")
}
首先检查 html 字符串是否包含嵌入推文的子字符串。 分配给 twitterJS 的脚本是我们从 twitter 网页上得到的。 从某种意义上说,最后一行很重要,它为我们的脚本命名。
实际身高评价是这样的:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "callbackHandler" {
print(message.body)
webViewx.evaluateJavaScript("document.body.offsetHeight", completionHandler: { (height, error) in
if let error = error {
print(error.localizedDescription)
return
}
if let height = height as? CGFloat{
if height > self.kontejnerHeight.constant {
self.kontejnerHeight.constant = height
}
}
})
}
}
希望这对其他人也有帮助。