Мое приложение использует WKWebView для представления html-строки. WkWebView встроен в scrollView, потому что у меня есть несколько других элементов (например, кнопки, tableViews). Из-за этого мне нужно рассчитать размер содержимого WkWebvView, и для этого я использую метод оценкиJavaScript ("document.body.scrollHeight", метод completHandler :. Когда бы я ни был встроен твит в строку html, высота контента ошибочно вычисляется, а мои разрезы webview кусок его высоты.
Часть html-строки, которая имеет вставку tweet, выглядит следующим образом:
<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, который мне пришлось заменить из-за правил stackoverflow)
Что-то не хватает в этом твиттер-коде, или я должен что-то установить в методах веб-просмотра?
Я попытался реализовать решение из этого сообщения: iOS Вычислить правильную высоту WKWebview для строки html с встроенным твитом, но не было никакого успеха или, по крайней мере, я мог бы найти ответ.
Любые советы приветствуются?
ОБНОВЛЕНИЕ: я немного взломал и нашел ужасное обходное решение, но это хорошее преимущество для проблемы. Это полная функция, которую я использую для расчета высоты:
'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 секунды. Теперь, каким образом можно получить обновление по высоте после правильного времени.
Кроме того, одна сторона примечания, если у меня есть встроенная фейсбук или пост instagram, все работает так, как должно быть, и высота веб-просмотра будет правильно рассчитана.
С помощью нескольких сообщений в stackoverflow (особенно: Twitter Uncaught TypeError: undefined не является функцией), и мой коллега, который является веб-разработчиком, мне удалось найти решение этой проблемы. В принципе, идея состоит в том, чтобы добавить скрипт в конфигурацию webview, если есть встроенный твит в строку html, которую нужно загружать веб-просмотру. После этого мы должны реализовать функцию messageContentController didReceive message, и в ней мы должны оценить высоту 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
}
}
})
}
}
Надеюсь, это поможет и другим.