使用WKWebView可以在JavaScript和Swift / Obj-C本机代码之间进行同步通信吗?
这些是我尝试过的并且失败的方法.
方法1:使用脚本处理程序
WKWebView接收JS消息的新方式是使用委托方法userContentController:didReceiveScriptMessage:从JS调用的是window.webkit.messageHandlers.myMsgHandler.postMessage(“生命的本机代码是什么意思?”)
这种方法的问题是在执行本机委托方法时,JS执行不被阻止,所以我们不能立即调用webView.evaluateJavaScript(“something = 42”,completionHandler:nil)来返回值.
示例(JavaScript)
var something; function getSomething() { window.webkit.messageHandlers.myMsgHandler.postMessage("What's the meaning of life,native code?"); // Execution NOT blocking here :( return something; } getSomething(); // Returns undefined
示例(Swift)
func userContentController(userContentController: WKUserContentController,didReceiveScriptMessage message: WKScriptMessage) { webView.evaluateJavaScript("something = 42",completionHandler: nil) }
在JS中,使用window.location =“js:// webView?hello = world”进行重定向调用本机WKNavigationDelegate方法,可以提取URL查询参数.但是,与UIWebView不同,委托方法不阻止JS执行,因此立即调用evaluateJavaScript将值传回给JS也不起作用.
示例(JavaScript)
var something; function getSomething() { window.location = "js://webView?question=meaning" // Execution NOT blocking here either :( return something; } getSomething(); // Returns undefined
示例(Swift)
func webView(webView: WKWebView,decidePolicyForNavigationAction navigationAction: WKNavigationAction,decisionHandler decisionHandler: (WKNavigationActionPolicy) -> Void) { webView.evaluateJavaScript("something = 42",completionHandler: nil) decisionHandler(WKNavigationActionPolicy.Allow) }
这种方法仅在分配window.location的方式上有所不同.而不是直接分配它,而是使用空的iframe的src属性.
示例(JavaScript)
var something; function getSomething() { var iframe = document.createElement("IFRAME"); iframe.setAttribute("src","js://webView?hello=world"); document.documentElement.appendChild(iframe); // Execution NOT blocking here either :( iframe.parentNode.removeChild(iframe); iframe = null; return something; } getSomething();
然而,这不是一个解决方案,它调用与方法2相同的本机方法,它不是同步的.
附录:如何用旧的UIWebView实现这一点
示例(JavaScript)
var something; function getSomething() { // window.location = "js://webView?question=meaning" // Execution is NOT blocking if you use this. // Execution IS BLOCKING if you use this. var iframe = document.createElement("IFRAME"); iframe.setAttribute("src","js://webView?question=meaning"); document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; return something; } getSomething(); // Returns 42
示例(Swift)
func webView(webView: UIWebView,shouldStartLoadWithRequest request: NSURLRequest,navigationType: UIWebViewNavigationType) -> Bool { webView.stringByEvaluatingJavaScriptFromString("something = 42") }
不,由于WKWebView的多进程架构,我不相信这是可能的. WKWebView与您的应用程序运行在相同的过程中,但它会与运行在其自身进程(
Introducing the Modern WebKit API)的WebKit进行通信. JavaScript代码将在WebKit进程中运行.因此,基本上你要求在两个不同的进程之间进行同步通信,这违反了他们的设计.
原文链接:https://www.f2er.com/swift/319822.html