iOS:哈希网址不工作在WKWebView,但工作在Safari浏览器

yhuiod9q  于 2023-03-20  发布在  iOS
关注(0)|答案(1)|浏览(168)

bounty将在7天后过期。回答此问题可获得+50声望奖励。Daniele B希望奖励现有答案

我尝试在iOS WKWebView上显示Web应用程序,但哈希URL似乎不起作用。
但是,如果我在iOS Safari上打开同一个网络应用程序,哈希网址可以正常工作。它们在Android WebView和Android Chrome上也可以正常工作。
使用此URL很容易验证问题:

  • 如果你在Safari上打开它并点击“搜索”按钮==〉它会正确显示结果页面。
  • 如果您在WKWebView上打开它并单击“搜索”按钮==〉,它会错误地显示一个空白屏幕。

根据this,WKWebView上的window.onhashchange事件似乎有一些问题。
是否有任何Swift或注入的Javascript代码可以解决这个问题,使Web应用程序在WKWebView上的行为与在Safari上的行为相同?

wnavrhmk

wnavrhmk1#

我能够通过使用linked question中的a solution和一点黑客来确定何时用更新后的URL重新加载Web视图来使其工作。
这里有一个小测试代码,可以复制到一个iOS斯威夫特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中。

相关问题