title: WKWebView in SwiftUI - How do I switch the view when user interacts with the website?
body: <p>My situation is the following: I have a SwiftUI application and want to display a WebView. When the user taps a certain button in that WebView I want the user to be redirected to the next (SwiftUI) view.
  I use a UIViewRepresentable as this seems to be the current way to go for showing a WebView in SwiftUI because it's the bridge to UIKit.
  The problem is: UIViewRepresentable has no <strong>body</strong>. So where do I tell the view to switch over? In usual SwiftUI views I would have a model which I'd update and then react on the model change in the body.</p>
  
  <p>I set up an example in which <a href="https://www.google.com" rel="noreferrer">https://www.google.com</a> is rendered in the WebView. When the user sends a search query the coordinator is called which calls a function of the UIViewRepresentable:</p>
  
  <p><strong>View</strong> - This is the view that should react on the model changes by displaying another view (implemented with <em>NavigationLinks</em>)</p>
  
  <pre><code>import SwiftUI
  
  struct WebviewContainer: View {
      @ObservedObject var model: WebviewModel = WebviewModel()
      var body: some View {
          return NavigationView {
              VStack {
                  NavigationLink(destination: LoginView(), isActive: $model.loggedOut) {
                      EmptyView()
                  }.isDetailLink(false)
                  .navigationBarTitle(Text(""))
                  .navigationBarHidden(self.model.navbarHidden)
  
                  NavigationLink(destination: CameraView(model: self.model), isActive: $model.shouldRedirectToCameraView) {
                      EmptyView()
                  }
                  .navigationBarTitle(Text(""))
                  .navigationBarHidden(self.model.navbarHidden)
                  Webview(model: self.model)
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>UIViewControllerRepresentable</strong> - This is necessary in order to use the WKWebview in SwiftUI context</p>
  
  <pre><code>import SwiftUI
  import WebKit
  
  struct Webview : UIViewControllerRepresentable {
      @ObservedObject var model: WebviewModel
  
      func makeCoordinator() -&gt; Coordinator {
          Coordinator(self)
      }
  
      func makeUIViewController(context: Context) -&gt; EmbeddedWebviewController {
          let webViewController = EmbeddedWebviewController(coordinator: context.coordinator)
          webViewController.loadUrl(URL(string:"https://www.google.com")!)
  
          return webViewController
      }
  
      func updateUIViewController(_ uiViewController: EmbeddedWebviewController, context: UIViewControllerRepresentableContext&lt;Webview&gt;) {
  
      }
  
      func startCamera() {
          model.startCamera()
      }
  }
  </code></pre>
  
  <p><strong>UIViewController</strong> - The WKNavigationDelegate that reacts on the click on "Google Search" and calls the coordinator</p>
  
  <pre><code>import UIKit
  import WebKit
  
  class EmbeddedWebviewController: UIViewController, WKNavigationDelegate {
  
      var webview: WKWebView
      var router: WebviewRouter? = nil
  
      public var delegate: Coordinator? = nil
  
      init(coordinator: Coordinator) {
          self.delegate = coordinator
          self.webview = WKWebView()
          super.init(nibName: nil, bundle: nil)
      }
  
      required init?(coder: NSCoder) {
          self.webview = WKWebView()
          super.init(coder: coder)
      }
  
      public func loadUrl(_ url: URL) {
          webview.load(URLRequest(url: url))
      }
  
      override func loadView() {
          self.webview.navigationDelegate = self
          view = webview
      }
  
      func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -&gt; Void) {
          guard let url = (navigationResponse.response as! HTTPURLResponse).url else {
              decisionHandler(.cancel)
              return
          }
  
          if url.absoluteString.starts(with: "https://www.google.com/search?") {
              decisionHandler(.cancel)
              self.delegate?.startCamera(sender: self.webview)
          }
          else {
              decisionHandler(.allow)
          }
      }
  
      override func viewDidLoad() {
          super.viewDidLoad()
      }
  }
  </code></pre>
  
  <p><strong>Coordinator</strong> - Bridge between <em>WKNavigationDelegate</em> and <em>UIViewRepresentable</em></p>
  
  <pre><code>import Foundation
  import WebKit
  
  class Coordinator: NSObject {
      var webview: Webview
  
      init(_ webview: Webview) {
          self.webview = webview
      }
  
      @objc func startCamera(sender: WKWebView) {
          webview.startCamera()
      }
  }
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I now have a View with a model (<strong>@ObservedObject</strong>). This model is given to the <strong>UIViewControllerRepresentable</strong>. When the user clicks "Google Search", <strong>UIViewControllerRepresentable</strong> successfully calls <strong>model.startCamera()</strong>. However, this change of the model is not reflected in the <strong>WebviewContainer</strong>. Why is that? Isn't that the whole purpose of <strong>@ObservedObject</strong>s? </p>