iOS:哈希 url 在 WKWebView 上不起作用,但在 Safari 浏览器上起作用

问题描述 投票:0回答:1

我正在尝试在 iOS 上显示网络应用程序

WKWebView
,但哈希 url 似乎不起作用。

但是,如果我在 iOS Safari 上打开相同的网络应用程序,哈希 url 将正常工作。它们也可以在 Android WebView 和 Android Chrome 上正常工作。

使用这个URL来验证问题非常容易:

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

根据 this WKWebView 上的

window.onhashchange
事件似乎存在一些问题。

是否有任何 Swift 或注入的 Javascript 代码可以解决此问题,以便 Web 应用程序在 WKWebView 上的行为与在 Safari 上的行为相同?

ios web-applications webview safari wkwebview
1个回答
0
投票

我能够通过使用链接问题中的解决方案和一点点黑客来确定何时使用更新的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
中。

© www.soinside.com 2019 - 2024. All rights reserved.