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)
}
}
}
这是我的 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
}
..但是在实现
@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)
}
}
}