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

如何在SwiftUI中向WKWebView子视图发送更新实现网页回退功能

SwiftUI WKWebView回退按钮失效问题修复方案

问题根因

  • updateUIView是SwiftUI视图更新流程中的回调方法,你在该方法内同步修改@Binding修饰的needsGoBack状态,等于在视图渲染过程中触发新的状态变更,因此会抛出「Modifying state during view update, this will cause undefined behavior.」警告,且状态无法被正确置为false,导致后续点击按钮时SwiftUI检测不到状态变化,不会触发updateUIView回调。
  • 原代码中使用@State修饰WKWebView实例属于不规范用法,@State仅适合存储和视图渲染相关的轻量值,不应用来持有UIKit视图实例。

修复代码

只需修改WebView.swift文件即可:

struct WebView: UIViewRepresentable {
    let urlString: String
    private let navigationHelper = WebViewHelper()
    @Binding var needsGoBack: Bool
    
    func makeUIView(context: Context) -> WKWebView {
        // 直接在makeUIView中创建WKWebView,由系统托管实例
        let webView = WKWebView()
        if let url = URL(string: urlString) {
            let request = URLRequest(url: url)
            webView.load(request)
        }
        webView.navigationDelegate = navigationHelper
        webView.uiDelegate = navigationHelper
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        guard needsGoBack else { return }
        // 用系统传入的uiView实例执行回退
        uiView.goBack()
        // 异步修改绑定状态,脱离当前视图更新周期
        DispatchQueue.main.async {
            needsGoBack = false
        }
    }
    
    typealias UIViewType = WKWebView
}

class WebViewHelper: NSObject, WKNavigationDelegate, WKUIDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("webview didFinishNavigation")
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("didStartProvisionalNavigation")
    }
    
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        print("webviewDidCommit")
    }
    
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print("didReceiveAuthenticationChallenge")
        completionHandler(.performDefaultHandling, nil)
    }
}

逻辑说明

  1. 移除了自定义存储的WKWebView实例,所有操作直接使用系统传入的托管实例,避免内存异常。
  2. 将状态重置操作放到主队列异步执行,等当前视图更新流程结束后再修改状态,既消除了警告,也能正确重置needsGoBack的值,后续每次点击回退按钮都能正常触发回退逻辑。
    ContentView代码无需修改即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:54:03