在 SwiftUI 中使用 WKWebView 和 UIViewRepresentable 时没有预览 - 已解决

no Preview in usage of WKWebView and UIViewRepresentable in SwiftUI - solved

提问人:biggreentree 提问时间:11/15/2023 最后编辑:biggreentree 更新时间:11/16/2023 访问量:25

问:

为什么我没有使用此代码进行预览?此代码在物理设备上工作,但我无法预览任何视图(忽略有关持久性数据的代码,我目前没有使用它)。使用 Xcode 14.2 “” 我在预览窗口中收到此消息“无法预览文件,预览服务消息无效”,但没有真正的错误

我的解决方案

我只是将 Xcode 更新到 14.3.1

我让下面的代码供将来参考

import SwiftUI
import WebKit

@main
struct TestCitrixSwiftUIApp: App {
    
    let persistenceController = PersistenceController.shared

    let classFromEntryPoint = ClassFromEntryPoint()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
                .environmentObject(classFromEntryPoint)
        }
    }
}


struct ContentView: View {
    
    @EnvironmentObject var classFromEntryPoint: ClassFromEntryPoint
    @State var cookies: [HTTPCookie] = []

    var body: some View {
        VStack {
            
            TextField("Insert exact url", text: $classFromEntryPoint.siteUrl)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
                .submitLabel(.go)
                .onSubmit {
                    classFromEntryPoint.loadValidUrl()
                }
            
            let _ = print("input: \(classFromEntryPoint.siteUrl)")
            
            if let url = URL(string: classFromEntryPoint.siteUrl) {
                LoadingWebView(url: url, shouldReload: $classFromEntryPoint.shouldReload, cookies: $cookies)
                    .edgesIgnoringSafeArea(.all)
            } else {
                Spacer()
                Text("Not a valid URL")
                Spacer()
            }
        }
    }
}

struct LoadingWebView: View {
    let url: URL
    @State private var isLoading = true
    @State private var error: Error? = nil
    @Binding var shouldReload: Bool
    @Binding var cookies: [HTTPCookie]

    var body: some View {
        ZStack {
            WebView(url: url, isLoading: $isLoading, error: $error, shouldReload: $shouldReload, cookies: $cookies)
                .edgesIgnoringSafeArea(.all)
            if isLoading {
                ProgressView()
            }
        }
    }
}

struct WebView: UIViewRepresentable {
    let url: URL
    @Binding var isLoading: Bool
    @Binding var error: Error?
    @Binding var shouldReload: Bool
    
    @Binding var cookies: [HTTPCookie]

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> WKWebView {
        let wkwebView = WKWebView()
        wkwebView.navigationDelegate = context.coordinator
        return wkwebView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        if shouldReload {
            uiView.load(URLRequest(url: url))
            DispatchQueue.main.async {
                self.shouldReload = false
            }
        }
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebView
        
        init(_ parent: WebView) {
            self.parent = parent
        }
        
        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            parent.isLoading = true
        }
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            parent.isLoading = false
            
            webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
                self.parent.cookies = cookies //foundamental
                print("found: \(cookies.count) cookies")
            }
        }
        
        func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
            parent.isLoading = false
            parent.error = error
        }
    }
}

class ClassFromEntryPoint: ObservableObject {
    
    @Published var siteUrl: String = "https://google.it"
    @Published var shouldReload: Bool = false
    
    init() {
        loadValidUrl()
    }
    
    func loadValidUrl() {
        let trimmedUrl = siteUrl.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmedUrl.hasPrefix("http://") && !trimmedUrl.hasPrefix("https://") {
            siteUrl = "https://" + trimmedUrl
        } else {
            siteUrl = trimmedUrl
        }
        shouldReload.toggle()
    }
}

// Preview
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(ClassFromEntryPoint())
    }
}
SwiftUI WKWebView UIViewRepresentable PreviewProvider

评论

0赞 Timmy 11/15/2023
我是抛出错误还是只是显示空白屏幕?
0赞 biggreentree 11/15/2023
我在预览窗口中收到此消息“无法预览文件,无效的预览服务消息”,但没有真正的错误,这就是我正在使用的所有代码
0赞 biggreentree 11/16/2023
我解决了将 Xcode 更新到 14.3.1 的问题

答: 暂无答案