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")!)
}
}
我目前正在使用 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")!)
}
}