Sheet 警报不断刷新我的 WKWebView SwiftUI 页面

Sheet and alert keeps refreshing my page for WKWebView SwiftUI

我目前正在使用 WKWebView,我在我的 wkwebview 中添加了一个 sheet 和一个警报。但是,每次我关闭 sheet 或关闭警报时,我的 WkWebView 都会继续导航(加载)回到我指定的原始域(对于这种情况,google.com)。我想知道如何解决这个问题。

网络视图

import SwiftUI
import WebKit

struct WebView : UIViewRepresentable {
    
    let request: URLRequest
    
    func makeUIView(context: Context) -> WKWebView  {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.load(request)
    }
    
}

主视图

struct MainView: View {
   var webView: WebView = WebView(request: URLRequest(url: URL(string: "https://www.google.com")!))

 var body: some View {
  VStack(){
   AlertView()
   webView
   SheetScreenView(webView: $webView)
  }
 }

AlertView()

...
  Button(action: {
  }, label: {}..alert(isPresented: $isBookmarked) {
                Alert(title: Text(" \(webView.getURL())"), dismissButton: .default(Text("Ok")))
            }
...

SheetScreenView

....
@State private var showingSheet = false

    var body: some View {
        Button("Show Sheet") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            SheetView()
        }
    }
...

工作表视图

struct SheetView: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        Button("Press to dismiss") {
            presentationMode.wrappedValue.dismiss()
        }
        .font(.title)
        .padding()
        .background(Color.black)
    }
}

即使没有 sheet 和警报,您的问题也可以重现,只需旋转设备即可。问题是在 updateView(将经常被调用)中,您在 URLRequest 上调用 load。由于您将视图存储在 var 中,这将在 MainView 的每个新渲染中重新创建,因为 SwiftUI 中的 Views 是瞬态的,这将使情况变得更加复杂.

如果您的 URL 不会改变 ,避免这种情况的最简单方法 就是在 makeUIView 中调用 load

struct WebView : UIViewRepresentable {
    var request: URLRequest
    
    func makeUIView(context: Context) -> WKWebView  {
        let webView = WKWebView()
        webView.load(request)
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        
    }
}

struct ContentView: View {
    var body: some View {
      WebView(request: URLRequest(url:URL(string: "https://www.google.com")!))
    }
}

如果您的 URL 可能 发生变化,您需要一种方法来比较以前的状态和新的状态。这似乎是最短的(但肯定不是唯一的)方法:

struct WebView : UIViewRepresentable {
    var url: URL
    
    @State private var prevURL : URL?
    
    func makeUIView(context: Context) -> WKWebView  {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        if (prevURL != url) {
            let request = URLRequest(url: url)
            uiView.load(request)
            DispatchQueue.main.async { prevURL = url }
        }
    }
}

struct ContentView: View {
    var body: some View {
        WebView(url: URL(string: "https://www.google.com")!)
    }
}