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

WebView中init Binding与View中State的兼容性问题

问题原因

核心问题源于SwiftUI View的值类型特性:

  • ItlnrView是值类型结构体,每次activeSheet状态变化时,整个结构体都会被重新初始化。
  • 你在结构体顶层用let webView = ...声明的实例,只会在ItlnrView第一次初始化时创建,后续View重构时该实例不会更新,它持有的Binding<Bool>还是旧的引用,无法和新的@State状态同步。
  • 直接在body中实例化myWebView时,每次body计算都会生成新实例,绑定的是最新的$activeSheet,因此状态同步正常。
解决方案

推荐方案:用ObservableObject封装WebView管理器

该方案既能持有WKWebView实例以调用返回、刷新功能,又能保证状态双向同步,同时符合SwiftUI的状态管理规范。

1. 创建WebView管理类

封装WKWebView实例、操作方法和状态:

class WebViewManager: ObservableObject {
    let webView: WKWebView
    @Published var activeSheet: Bool = false // 内部维护sheet状态
    
    init(request: URLRequest) {
        self.webView = WKWebView()
        self.webView.load(request)
    }
    
    // 实现返回功能
    func goBack() {
        if webView.canGoBack {
            webView.goBack()
        }
    }
    
    // 实现刷新功能
    func reload() {
        webView.reload()
    }
}

2. 修改UIViewRepresentable实现

通过@ObservedObject关联管理器(注意:Swift类型名需遵循大驼峰规范,将myWebView改为MyWebView):

struct MyWebView: UIViewRepresentable {
    @ObservedObject var manager: WebViewManager
    
    func makeUIView(context: Context) -> WKWebView {
        manager.webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        // 可在此添加WebView与管理器状态的同步逻辑
    }
}

3. 在主View中使用并同步状态

struct ItlnrView: View {
    @State var activeSheet: Bool = false
    @StateObject private var webViewManager = WebViewManager(
        request: URLRequest(url: URL(string: "https://google.com")!)
    )
    
    var body: some View {
        VStack {
            MyWebView(manager: webViewManager)
            
            // 添加操作按钮,直接调用管理器方法
            HStack {
                Button("返回") {
                    webViewManager.goBack()
                }
                Button("刷新") {
                    webViewManager.reload()
                }
            }
            .padding()
        }
        .sheet(isPresented: $activeSheet) {
            // Sheet内容
        }
        // 双向同步主View与管理器的sheet状态
        .onChange(of: activeSheet) { newValue in
            webViewManager.activeSheet = newValue
        }
        .onChange(of: webViewManager.activeSheet) { newValue in
            activeSheet = newValue
        }
    }
}

替代方案:用@State延迟初始化WebView实例

若不想额外创建管理类,可使用@State延迟初始化WebView,确保实例在View生命周期内保持并绑定最新状态:

struct ItlnrView: View {
    @State var activeSheet: Bool = false
    @State private var webView: MyWebView?
    
    var body: some View {
        VStack {
            webView ?? MyWebView(manager: WebViewManager(request: URLRequest(url: URL(string: "https://google.com")!)))
                .onAppear {
                    // 第一次出现时初始化WebView实例
                    if webView == nil {
                        webView = MyWebView(manager: WebViewManager(request: URLRequest(url: URL(string: "https://google.com")!)))
                    }
                }
        }
        .sheet(isPresented: $activeSheet) {
            // Sheet内容
        }
    }
}

注:推荐优先使用ObservableObject方案,它的扩展性更强,更易维护复杂的WebView逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 12:45:37