在 WKWebView 中使用 callAsyncJavaScript

zzh*_*ads 1 javascript swift wkwebview

方法callAsyncJavaScript和之间有什么区别evaluateJavaScript?将其与相同的脚本一起使用,例如:

evaluateJavaScript("document.documentElement.outerHTML.toString()")
Run Code Online (Sandbox Code Playgroud)

和

callAsyncJavaScript("document.documentElement.outerHTML.toString()")
Run Code Online (Sandbox Code Playgroud)

返回不同的结果:第一个是 HTML,第二个是 .sucess(nil)...

Kir*_* S. 8

有 3 种方法允许从 WKWebView 运行 JS(当然,还有更多签名,但有 3 种主要方法):

  • 最古老和最原始的是evaluateJavaScript(_:completionHandler:),它允许运行任意代码段。如今,没有任何借口可以使用,因为它比其他方法没有任何好处。

  • 更现代的改进版本是evaluateJavaScript(_:in:in:completionHandler:)在 iOS 14 中引入的。它可用于运行同步代码。它使用现代方式来呈现结果 - Result<Any, Error>,它允许将任何类型的结果(成功或失败)封装在一个方便使用的对象中。但关键的区别在于它允许您指定脚本的上下文,这可以防止不同脚本之间的冲突:

在其自己的内容世界中执行脚本可以有效地为其提供要修改的环境变量的单独副本。

  • 但这些函数都无法支持异步 JavaScript 代码,即Promise。如果你结合使用(例如,如这里所解释的),你可以实现承诺执行,但这非常尴尬。因此解决了这个问题:您可以使用它来执行 Promise,而无需 的额外帮助,这使得代码分布更少,并且更容易。下面是一个示例,说明它是如何完成的。evaluateJavaScriptWKScriptMessagecallAsyncJavaScript(_:arguments:in:in:completionHandler:)WKScriptMessage

此方法还有 2 个额外优点:

  • 第一个参数不再是函数名,而是functionBody,成为匿名函数,防止由于函数的全局作用域而可能出现的命名冲突。
  • 而且参数与主体分离[String : Any],这允许我们在某处静态定义函数主体,并通过传递参数来重用它(而不是像您需要的那样将它们注入到函数主体中)evaluateJavaScript。

所以你应该使用这个方法来执行异步JS代码,并且你可以使用它来执行同步代码。

还有一件事:callAsyncJavaScript你需要记住你正在定义函数体,所以如果你想要返回一些东西,你需要使用这个词return(而不是evaluateJavaScript,你定义了一段要运行的代码,它可以没有return,除非你定义了一个函数)。