我正在尝试在 iOS 上显示网络应用程序
WKWebView
,但哈希 url 似乎不起作用。
但是,如果我在 iOS Safari 上打开相同的网络应用程序,哈希 url 将正常工作。它们也可以在 Android WebView 和 Android Chrome 上正常工作。
使用这个URL来验证问题非常容易:
根据 this WKWebView 上的
window.onhashchange
事件似乎存在一些问题。
是否有任何 Swift 或注入的 Javascript 代码可以解决此问题,以便 Web 应用程序在 WKWebView 上的行为与在 Safari 上的行为相同?
我能够通过使用链接问题中的解决方案和一点点黑客来确定何时使用更新的URL重新加载网络视图来实现这一点。
这里有一些可以复制到 iOS Swift Playground 中的测试代码。
import UIKit
import WebKit
class WebVC: UIViewController, WKNavigationDelegate {
var webView: WKWebView!
var pending = false
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView()
webView.navigationDelegate = self
webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
webView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
webView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
])
}
// Code from the linked answer
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if object as AnyObject? === webView && keyPath == "URL" {
print(webView.url)
if let url = webView.url, pending {
// Probably need to add a sanity check to avoid a reload loop.
// Not sure if that can happen in some corner case or not.
let req = URLRequest(url: url)
webView.load(req)
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let req = URLRequest(url: URL(string: "https://www.lefrecce.it/Channels.Website.WEB/#/white-label/MINISITI/?minisitiCallBackId=54276&isRoundTrip=false&lang=en&departureStation=Salerno&arrivalStation=Caserta")!)
webView.load(req)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, preferences: WKWebpagePreferences) async -> (WKNavigationActionPolicy, WKWebpagePreferences) {
print("decidePolicyFor action, prefs: \(preferences)")
pending = true
return (.allow, preferences)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("didFinish \(navigation)")
pending = false
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("Error: \(error)")
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print("Provisional error: \(error)")
}
}
PlaygroundPage.current.liveView = WebVC()
整个
pending
标志是对解决方案的第一次尝试。它可能有点脆弱,但在这种情况下有效。可能存在极端情况,最终导致重新加载循环,因此需要进一步测试以确保。
还需要添加代码来移除
webView
中的观察者。可能在视图控制器的deinit
中。