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
}
}
}
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)")
}
}
}