Как мне запустить команду javascript в WKWebView Swift

#javascript #ios #swift #webview #java-console

#javascript #iOS #swift #webview #java-консоль

Вопрос:

Я пытаюсь запустить команду javascript, которая работает, если я запускаю ее в консоли в Интернете. Я пытался выполнить приведенный ниже код, но в ответ продолжаю получать nil.

 webView.evaluateJavaScript("command") { (result, error) in
     if error == nil {
          print(result)
     } else {
          print(error)
     }
}
  

Комментарии:

1. Для исправления if error != nil { print(result) } это означает, что это ошибка —&&t; Тогда результата нет.

2. Я исправил это, и вот ошибка, которую я получаю: Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessa&e=TypeError: undefined is not an object, WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred Я просто хочу запустить команду, которая, как я точно знаю, работает, когда я помещаю ее в консоль javascript в Chrome на моем компьютере. Возможно ли это?

3. Протестируйте свою команду непосредственно в WKWebView. Вы можете подключить веб-инспектор настольного Safari к веб-представлению, которое в данный момент открыто в симуляторе iOS.

4. Пример команды javascript, которую вы могли бы попробовать, это (() =&&t; { return 5 })(); и посмотреть, получите ли вы 5 баллов за результат на iOS. Javascript просто создает и запускает функцию, которая возвращает значение 5.

Ответ №1:

В случае, если ваш webview дополнительно загружает часть body (или весь html body), вы не получите желаемых результатов, оценив ваш javascript внутри метода:

 func webView(_ webView: WKWebView, didFinish navi&ation: WKNavi&ation!) 
  

Причина этого в том, что метод «didFinish» вызывается после завершения навигации внутри webview, но не строго после загрузки всего содержимого внутри WebView, которое может находиться в состояниях:

  1. состояние: пустое тело
  2. состояние: некоторая загрузка
  3. состояние: javascript framework выполнил свою работу и вставил тело приложения внутрь
  4. состояние: тело содержит содержимое

«didFinish» вызывается в состоянии 1. Вы можете подождать некоторое время с DispatchQueue.main.asyncAfter, а затем выполнить .evaluateJavascript, но это приведет к тому, что WebView внесет изменения перед пользователем (на мой взгляд, некрасиво …)

Моим предложением было бы это расширение:

 extension WKWebView {

// it re-execute javascript in cases when body is attached additionally on the html by some inner javascript framework
// it tries around 50 times maximum in time ran&e of 10 sec
// if body is not loaded in 10 secs, this won't work
func rexecuteJavascript(tryouts: Int = 0, script: Strin&) {
    self.evaluateJavaScript(script, completionHandler: { (result: Any?, error: Error?) in
        if let _ = error, tryouts < 50 {
            DispatchQueue.main.asyncAfter(deadline: .now()   0.2) {
                return self.rexecuteJavascript(tryouts: tryouts   1, script: script)
            }
        }
    })
}
  

}

У меня это работает идеально, потому что тело webview заполняется примерно через 2-3 секунды после «didFinish», и я использую это для выполнения моего javascript в полностью загруженном теле:

 func webView(_ webView: WKWebView, didFinish navi&ation: WKNavi&ation!) {
    let removeFooterScript = "document.&etElementsByClassName('&lobal-footer')[0].style.display='none';"

    webView.rexecuteJavascript(script: removeFooterScript)
}
  

Приветствия!

Ответ №2:

Вот код для внедрения кода javascript в ваш WKWebView

 let wkUScript = WKUserScript(source: "your javascript command",
                             injectionTime: .atDocumentEnd,
                             forMainFrameOnly: true)
let wkUController = WKUserContentController()
wkUController.addUserScript(wkUScript)

let wkWebConfi& = WKWebViewConfi&uration()
wkWebConfi&.userContentController = wkUController

let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 400, hei&ht: 400), confi&uration: wkWebConfi&)
  

Комментарии:

1. Как бы вы распечатали ответ?

2. Вы устанавливаете webView.UIDele&ate = self , а затем вызываете этот делегат: func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessa&e messa&e: Strin&, initiatedByFrame frame: WKFrameInfo, completionHandler: @escapin& () -&&t; Void) { print(messa&e) }