如何在WKWebView中检测哈希值的更改?

5
我有一个网站,使用JavaScript和Angular控制网站上的内容显示。当你单击标签时,网址会从http://somewebsite.com/#page1更改为http://somewebsite.com/#page2,但实际上没有重新加载网站,因此func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)将不会被触发。如何捕获这些哈希更改?
显然,Safari网络浏览器能够在地址栏中显示这些更改。
更新19.33: 我进行了一些研究。在Safari浏览器中,使用window.onhashchange可以触发它,但在WKWebView中却不行。我使用以下JavaScript每秒返回一次文档位置href。
window.setInterval(function(){ alert(document.location) }, 1000);

当在WKWebView中阅读警报时,它从未显示位置更改,而在Safari中,您可以看到http://somewebsite.com/#page1http://somewebsite.com/#page2。看起来WKWebView不支持这个极其恼人的功能。


1
你解决了这个问题吗?我也遇到了同样的问题。 - priya_d
2个回答

4
无需注入任何JS。我使用了webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil),这可以检测到任何URL更改,包括哈希值的更改。然后:
override func observeValue(
    forKeyPath keyPath: String?,
    of object: Any?,
    change: [NSKeyValueChangeKey: Any]?,
    context: UnsafeMutableRawPointer?) {
  if object as AnyObject? === webView && keyPath == "URL" {
    onURLChange(webView.url) // onURLChange does whatever you want
  }
}

不过在 `deinit` 块中不要忘记移除观察器,即 webView.removeObserver(self, forKeyPath: "URL")

非常好的答案!谢谢——这应该是被采纳的答案。 - PaulJ

1
let script = WKUserScript(source: "(function() { \"use strict\"; addEventListener(\"hashchange\", function(event) { webkit.messageHandlers.hashchangeMessageHandler.postMessage(null); }); }) ();", injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)

let configuration = WKWebViewConfiguration()
configuration.userContentController.add(self, name: "hashchangeMessageHandler")
configuration.userContentController.addUserScript(script)

self.webView = WKWebView(frame: CGRect.zero, configuration: configuration)

现在你可以使用以下代码获取已更改哈希值的URL:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print("Received message: \(message.name): \(message.body)")
    print(self.webView.url)

}

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