SwiftUI:WebKit 在键入时持续加载页面 url

SwiftUI: WebKit is loading page continuously when typing url

这是我的 macOS 应用程序中的 URL 地址栏,它与此 TextField 一起工作正常:

@State private var text = ""
@State private var site = "www.google.com/" //stored as two separate values so that WebKit isn't trying to continuously load a URL with every single keystroke. The "site" property is only updated once the user presses the return key.

var body: some View {

let webView = WebView(site: $site, text: $text)
    
        TextField("Enter a URL", text: $text, onCommit: {
                guard !text.isEmpty else {return}
                site = text
            })
             webView //To display the loaded web page
                    }

..但是在实现 后,当用户将 URL 复制并粘贴到地址栏时删除“https://”,WebKit 现在正在尝试连续加载 URL 每一次击键,我的应用程序都会停止工作。

@State private var text = ""
@State private var site = "www.google.com/"


var body: some View {

let webView = WebView(site: $site, text: $text)

    TextField("Enter a URL", text: Binding(
                    get: { text },
                               set: { newValue in
                                   if trim(newValue).starts(with: "https://") {
                                       text = String(trim(newValue).dropFirst(8))
                                   } else {
                                       text = newValue
                                   }
                               }), onCommit: {
                                
            guard !text.isEmpty else {return}
            site = text
        })
webView //To display the loaded web page

}

     func trim(_ str: String) -> String {
            return str.trimmingCharacters(in: .whitespacesAndNewlines)
        }
        

网络视图

struct WebView: NSViewRepresentable {
@Binding var site: String
private var webView: WKWebView


init(site: Binding<String>, text: Binding<String>) {
    self.webView = WKWebView()
    _site = site // 
    
}

func makeNSView(context: Context) -> WKWebView {
    return webView
}

func updateNSView(_ nsView: WKWebView, context: Context) {
    nsView.load(URLRequest(url: (URL(string: "https://" + site) ?? Bundle.main.url(forResource: "URLError", withExtension: "pdf")!)))
}

抱歉,删除了我之前的代码,因为它不适合针对 macOS 10.15 的 Big Sur 11.3。

可能是因为“文本”在不断更新:

let webView = WebView(site: $site, text: $text)

删除您不使用的“文本”部分,并相应地调整“WebView”初始化:

let webView = WebView(site: $site)

编辑 2:

为了完整起见,这是我在 macos 12 上运行的测试代码(因为这是我唯一的测试代码) 但应该适用于 macos 11.3。它使用 ObservableObject 来进行绑定。

import Foundation
import SwiftUI
import WebKit


extension String {
    func trim() -> String {
        return self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
}

class WebStateModel: ObservableObject {
    @Published var url: URL? = URL(string: "https://www.google.com")
    
    func updateUrl(_ str: String) {
        if let theUrl = URL(string: "https://" + WebStateModel.stripHttps(str)) {
            url = theUrl
        }
    }
    
    static func stripHttps(_ str: String) -> String {
        var txt = str.trim()
        if txt.starts(with: "https://") {
            txt = String(txt.dropFirst(8))
        }
        return txt
    }
}

struct ContentView: View {
    @StateObject var webModel = WebStateModel()
    @State var text = ""
    
    var body: some View {
        VStack (spacing: 80) {
            TextField("Enter a URL", text: Binding(
                get: { text },
                set: { text = WebStateModel.stripHttps([=12=]) } ), onCommit: {
                    webModel.updateUrl(text)
                })
            WebView(webModel: webModel)
        }
    }
}

struct WebView: NSViewRepresentable {
    @ObservedObject var webModel: WebStateModel

    func makeNSView(context: Context) -> WKWebView {
        let wkWebview = WKWebView()
        if let theUrl = webModel.url {
            let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
            wkWebview.load(request)
        }
        return wkWebview
    }

    func updateNSView(_ nsView: WKWebView, context: Context) {
        if let theUrl = webModel.url {
            let request = URLRequest(url: theUrl, cachePolicy: .returnCacheDataElseLoad)
            nsView.load(request)
        }
    }
}