You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中WKWebView哈希URL失效问题求助(Safari可正常运行)

WKWebView 哈希URL(window.onhashchange)问题修复方案

针对你遇到的WKWebView中哈希URL无法正常触发window.onhashchange事件、点击搜索后显示空白的问题,可通过以下两种方案解决:

一、Swift端配置与导航拦截

通过配置WKWebView基础属性,并拦截哈希导航动作,强制触发哈希变化事件:

import WebKit

class WebViewController: UIViewController, WKNavigationDelegate {
    private var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let config = WKWebViewConfiguration()
        // 启用JavaScript(Web应用核心逻辑依赖此设置)
        config.preferences.javaScriptEnabled = true
        // 允许JavaScript打开新窗口(适配部分Web应用的交互逻辑)
        config.preferences.javaScriptCanOpenWindowsAutomatically = true
        
        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)
        
        // 加载目标URL
        guard let targetURL = URL(string: "https://www.lefrecce.it/Channels.Website.WEB/#/white-label/MINISITI/?minisitiCallBackId=54276&isRoundTrip=false&lang=en&departureStation=Salerno&arrivalStation=Caserta") else { return }
        webView.load(URLRequest(url: targetURL))
    }
    
    // 拦截哈希导航,强制触发hashchange事件
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        guard let requestURL = navigationAction.request.url, requestURL.fragment != nil else {
            decisionHandler(.allow)
            return
        }
        
        decisionHandler(.allow)
        // 手动触发hashchange事件,确保Web应用捕获到哈希变化
        webView.evaluateJavaScript("""
            window.dispatchEvent(new HashChangeEvent('hashchange', {
                oldURL: window.location.href,
                newURL: '\(requestURL.absoluteString)'
            }))
        """) { _, error in
            if let err = error {
                print("触发hashchange失败: \(err.localizedDescription)")
            }
        }
    }
}

二、注入JavaScript修补哈希事件

部分Web应用依赖history.pushState/replaceState修改哈希(这两个方法不会自动触发hashchange),可注入JS重写这些方法并强制触发事件:

在Swift中,通过WKNavigationDelegate的didFinishNavigation方法注入修复代码:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    let hashFixScript = """
    // 保存原生事件处理逻辑
    const originalOnHashChange = window.onhashchange;
    let lastHash = window.location.hash;

    // 定时检查哈希变化,手动触发事件
    setInterval(() => {
        const currentHash = window.location.hash;
        if (currentHash !== lastHash) {
            const hashEvent = new HashChangeEvent('hashchange', {
                oldURL: window.location.origin + window.location.pathname + lastHash,
                newURL: window.location.origin + window.location.pathname + currentHash
            });
            // 执行原生事件处理
            if (originalOnHashChange) originalOnHashChange.call(window, hashEvent);
            // 触发全局事件
            window.dispatchEvent(hashEvent);
            lastHash = currentHash;
        }
    }, 100);

    // 重写pushState,触发hashchange
    const originalPushState = history.pushState;
    history.pushState = function(state, title, url) {
        originalPushState.call(this, state, title, url);
        const hashEvent = new HashChangeEvent('hashchange', {
            oldURL: window.location.href,
            newURL: window.location.origin + window.location.pathname + url
        });
        window.dispatchEvent(hashEvent);
    };

    // 重写replaceState,触发hashchange
    const originalReplaceState = history.replaceState;
    history.replaceState = function(state, title, url) {
        originalReplaceState.call(this, state, title, url);
        const hashEvent = new HashChangeEvent('hashchange', {
            oldURL: window.location.href,
            newURL: window.location.origin + window.location.pathname + url
        });
        window.dispatchEvent(hashEvent);
    };
    """
    
    webView.evaluateJavaScript(hashFixScript) { _, error in
        if let err = error {
            print("注入哈希修复脚本失败: \(err.localizedDescription)")
        } else {
            print("哈希修复脚本注入成功")
        }
    }
}

关键注意事项

  • 必须确保WKWebView的javaScriptEnabled为true,否则所有Web交互逻辑都会失效;
  • 定时检查的间隔(示例中为100ms)可根据Web应用的响应速度调整,间隔越小响应越及时,但会增加少量性能开销;
  • 若Web应用使用Vue、React等前端框架的哈希路由,上述方案可确保框架路由监听器捕获到哈希变化,正常渲染页面。

内容的提问来源于stack exchange,提问作者Daniele B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:17:03