【问题标题】:How do I run a javascript command in WKWebView Swift如何在 WKWebView Swift 中运行 javascript 命令
【发布时间】:2020-11-29 15:46:44
【问题描述】:

我正在尝试运行一个 javascript 命令,如果我在网络上的控制台中运行它就可以工作。我已经尝试执行下面的代码,但我的响应一直是 nil。

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

【问题讨论】:

  • 为了更正if error != nil { print(result) }这意味着错误--->那么没有结果。
  • 我修复了它,这是我得到的错误:Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=TypeError: undefined is not an object, WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred 我只想运行一个命令,当我将它放在我电脑上的 chrome 中的 javascript 控制台中时,我知道它肯定有效。这可能吗?
  • 直接在 WKWebView 中测试你的命令。您可以将桌面 Safari 的网络检查器附加到当前在 iOS 模拟器中打开的网络视图。
  • 您可以尝试的示例 javascript 命令是 (() => { return 5 })();,看看您在 iOS 上的结果是否为 5。 javascript 只是创建并运行一个返回值 5 的函数。

标签: javascript ios swift webview java-console


【解决方案1】:

这是在 WKWebView 中注入 javascript 代码的代码

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

let wkWebConfig = WKWebViewConfiguration()
wkWebConfig.userContentController = wkUController

let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 400, height: 400), configuration: wkWebConfig)

【讨论】:

  • 如何打印出响应?
  • 你设置webView.UIDelegate = self 然后调用这个代理:func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { print(message) }
【解决方案2】:

如果您的 webview 额外加载了部分正文(或整个 html 正文),那么通过在方法内部评估您的 javascript,您将不会获得预期的结果:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) 

这样做的原因是,一旦在 webview 内完成导航,就会调用“didFinish”方法,但不是严格地在将可能处于状态的 webView 内的全部内容加载之后:

  1. 状态:空体
  2. 状态:正在加载中
  3. 状态:javascript 框架完成了他的工作并在其中插入了 app-body
  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 range of 10 sec
// if body is not loaded in 10 secs, this won't work
func rexecuteJavascript(tryouts: Int = 0, script: String) {
    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 的主体在“didFinish”之后大约 2-3 秒内被填充,我使用它在完全加载的主体上执行我的 javascript:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    let removeFooterScript = "document.getElementsByClassName('global-footer')[0].style.display='none';"

    webView.rexecuteJavascript(script: removeFooterScript)
}

干杯!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多