iOS WKWebView неправильно вычисляет высоту при наличии встроенного твита

1

Мое приложение использует 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, все работает так, как должно быть, и высота веб-просмотра будет правильно рассчитана.

Теги:
wkwebview
webview
twitter

1 ответ

0
Лучший ответ

С помощью нескольких сообщений в 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
                }

            }
        })
    }
}

Надеюсь, это поможет и другим.

  • 0
    У вас есть пример проекта этого?
  • 0
    Привет @karthikeyan, у меня нет примера проекта в данный момент. Если вы не можете сделать эту работу, я с радостью помогу вам, если вы добавите меня в качестве соавтора в ваш проект. Кроме того, другой мой ответ для расчета высоты WKWebView может дать вам более широкую картину: stackoverflow.com/a/45674575/7373604 .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню