SwiftUI - WebView

168 Views Asked by At

fairly new to SwiftUI, so thank you in advance. Inside the init of the Coordinator we pass the WebView to let the Coordinator know who the parent is, but the WebView being a struct, wouldn't Coordinator be having a new copy of the WebView instead of the original?

If so, why is this approach commonly mentioned? Would it be better to create a new class(ObservableObject) and let WebView create an object of the class and pass the class into the Coordinator?

   struct WebView: UIViewRepresentable {
    var url: URL

    func makeCoordinator() -> WebView.Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> WKWebView {
        let view = WKWebView()
        view.navigationDelegate = context.coordinator
        view.load(URLRequest(url: url))
        return view
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {}

    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebView

        init(_ parent: WebView) {
            self.parent = parent
        }
    }
}
1

There are 1 best solutions below

1
meomeomeo On BEST ANSWER

Yes, Coordinator holds a copy of original WebView, you understand it right. But its purpose is not what you think.

First, you need to understand that WebView doesn't hold WKWebView, its purpose is giving information how to update WKWebView to fit your intent, and Coordinator is helping it by keeping a copy of WebView

How is it helping ? Usually to track old version (latest version, or first version) of WebView so you can get its infomations if needed

func updateUIView(_ uiView: WKWebView, context: Context) {
    let lastURL = context.coordinator.parent.url
    print(lastURL)
    context.coordinator.parent = self // (*)
}
/// be cause of (*), next time lastURL will be the previous URL
/// without (*), lastURL always be the first URL you used to init WKWebView

Here's another small example you can see on Preview how UIViewRepresentable works

struct LabelView: UIViewRepresentable {
    var text: String
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel(frame: .init(x: 0, y: 0, width: 100, height: 100))
        label.text = text
        return label
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        let lastLabel = context.coordinator.parent.text
        uiView.text = "\(lastLabel) -> \(text)"
        context.coordinator.parent = self
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: LabelView

        init(_ parent: LabelView) {
            self.parent = parent
        }
    }
}
struct TestLabelView: View {
    @State private var num = 0
    var body: some View {
        Button { num += 1 } label: {
            LabelView(text: "\(num)")
        }
    }
}