在Swift WKWebView中捕获window.postMessage

10

我正在开发一个Swift iOS应用程序,使用WKWebView加载电子商务网站。
当用户在此购买产品时,结账页面允许用户使用加密货币进行支付。

当用户点击“在钱包中打开”时,该网站会发送一个window.postMessage(paymentData),其中payment data是一个js对象,其中包含比特币url。

我正在使用WKUserScriptWKWebConfiguration注入一个脚本,监听窗口消息,然后将数据发送到我的webkit.messageHandler

let source = """
    window.addEventListener('message', function(e) { window.webkit.messageHandlers.iosListener.postMessage(JSON.stringify(e.data)) } )
    """

很遗憾,这段代码从未触发。

当我使用 Chrome 或 Safari 开发工具注入相同的 JavaScript 时,它可以正常工作。

我已经在 Stack Overflow 上搜索过了,在 WKWebView 中是否有关于 window.postMessage 的特殊条件,但迄今为止没有找到。

是否有可能捕获 window.postMessage() 事件并将事件数据返回到我的 iOS 应用程序?

提前致谢!!!这是我现有的代码。

  let webConfiguration = WKWebViewConfiguration()
    let source = """
    window.addEventListener('message', function(e) { window.webkit.messageHandlers.iosListener.postMessage(JSON.stringify(e.data)) } )
    """
    let script = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
    userContentController.addUserScript(script)

    userContentController.add(self, name: "iosListener")
    webConfiguration.userContentController = userContentController
    webView = WKWebView(frame: .zero, configuration: webConfiguration)
    webView.uiDelegate = self
    webView.navigationDelegate = self
    webView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(webView)
 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print("message body: \(message.body)")
    print("message frameInfo: \(message.frameInfo)")
  }

2
你解决了吗?考虑给答案点赞/接受/互动,以产生对网站有价值的知识。问问题后从不回来并不是一个好习惯。 - Gustavo Vollbrecht
1
嗨@GustavoVollbrecht。我去度假了,希望我能得到更多的答案。感谢您的贡献,但不幸的是我们仍然无法捕获window.postMessage事件。奇怪的是,我们可以捕获任何其他事件,比如onClick。具体来说,我们无法捕获window.postMessage(JSON.stringify(data), '*');。 如果您有兴趣,我可以与您分享该网站的URL。 再次感谢。我已经为您的答案点赞。 - MFD3000
2
@MFD3000,你解决了吗?我也遇到了这个问题。在更改为injectionTime: .atDocumentStart后,我成功地让它工作了。 - Janno Teelem
1
@JannoTeelem:我的代码现在也可以在使用atDocumentStart时工作。如果这个答案对OP有用的话,那就很有趣了。 - testing
1
@MFD3000 我遇到了类似的问题,你解决了吗? - subha
不幸的是,我在那个特定问题上不是负责人。负责人选择以工作解决方案为代价来实现良好的用户体验。 如果有人在这里提供的任何解决方案中有所帮助,我很乐意将其标记为已解决。 - MFD3000
1个回答

13

是的,这是可能的。您还需要设置javascriptEnabled = true

self.webView.configuration.preferences.javaScriptEnabled = true

您还可以像这样配置监听器:

self.webView.configuration.userContentController.add(self, name: "iosListener")

确保在之前都应用了这两个命令

self.webView.load(/*some request*/)

页面didFinish加载后,您可以使用以下方法进行简单测试:

self.webView.evaluateJavaScript("window.webkit.messageHandlers.iosListener.postMessage('test');", completionHandler: { (result, err) in
    if (err != nil) {
        // show error feedback to user.
    }
})

另一个建议是,在与 webView 交互的 JavaScript 代码中,命令的末尾始终要有 ;,因为有些命令依赖于标准 JavaScript。

let source = """
    window.addEventListener('message', function(e) {
        window.webkit.messageHandlers.iosListener.postMessage(JSON.stringify(e.data));
    });
    """
注意: 我建议将webView作为类变量而不是方法变量,并且您可能会在viewDidLoad()上创建它,建议将变量移动到您的类中。 var webView: WKWebView!

@SmarterSusheel在他的下一行,WKUserScript init - Gustavo Vollbrecht
1
@GustavoVollbrecht 我需要在iOS应用程序中监听第三方支付响应,我正在使用上述消息事件侦听器,但是在接收到第三方响应后,userContentController方法没有被触发,而其他侦听器例如focus、click则可以触发userContentController。请给予建议。 - subha
@subha 请发布您自己的问题,并提供尽可能多的细节。 - Gustavo Vollbrecht

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接