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

61 views Asked by At

Why I am not getting a preview with this code? This code is working on physical device, but I cannot get preview for none of my views (ignore code about persistent data, I'm not using it at this moment). Using Xcode 14.2 "" I got in preview window this message "cannot preview file, invalid preview service message" but no a real error

MY SOLUTION

I simply updated Xcode, to 14.3.1

I let the code below for future reference

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())
    }
}
0

There are 0 answers