3

I was wondering how I can display my current URL on WKWebView and display URL on change also. Currently I added a Text() but it does not display the URL at all. Any ideas how I can fix it?

WebView

import SwiftUI
import WebKit

struct WebView : UIViewRepresentable {
    
    let request: URLRequest
    private var webView: WKWebView?

    init (request: URLRequest) {
        self.webView = WKWebView()
        self.request = request
    }
    
    func makeUIView(context: Context) -> WKWebView  {
        webView?.load(request)
        return webView!
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
    
    }

    func URL() -> String {
        return (webView?.url)?.absoluteString ?? ""
    }

    func goBack() {
        webView?.goBack()
    }
    
    func goForward() {
        webView?.goForward()
    }
    
}

MainView

struct MainView: View {
   var webView: WebView = WebView(request: URLRequest(url: URL(string: "https://www.google.com")!))

 var body: some View {
  VStack {
   //...
   Text(webView.URL())
   webView
   Button(action: { webView.goBack() }, label: { Text("Test") })
//...
  }
 }
egeeke
  • 753
  • 1
  • 6
  • 18
James Lee
  • 656
  • 1
  • 7
  • 22
  • The way that you're structuring this (which shares the same problem with your previous question that I answered) is possibly going to affect how this will work. You may want to address that issue first. – jnpdx Mar 28 '21 at 04:27
  • @jnpdx I just saw ur answer. I edit my answer accordingly. Thanks for the help again! – James Lee Mar 28 '21 at 05:01

1 Answers1

5

To keep track of the URL of the WKWebView, you'll need to use a WKNavigationDelegate.

You can use a Coordinator in your UIViewRepresentable for the WKNavigationDelegate and an ObservableObject with a @Published value to communicate between the WebView and your parent view:

class NavigationState : ObservableObject {
    @Published var url : URL?
}

struct WebView : UIViewRepresentable {
    
    let request: URLRequest
    var navigationState : NavigationState
    
    func makeCoordinator() -> Coordinator {
        return Coordinator()
    }
    
    func makeUIView(context: Context) -> WKWebView  {
        let webView = WKWebView()
        context.coordinator.navigationState = navigationState
        webView.navigationDelegate = context.coordinator
        webView.load(request)
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        
    }

    class Coordinator : NSObject, WKNavigationDelegate {
        var navigationState : NavigationState?
        
        func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
            navigationState?.url = webView.url
        }
    }
    
}

struct ContentView: View {
    @StateObject var navigationState = NavigationState()
    
    var body: some View {
        VStack(){
            Text(navigationState.url?.absoluteString ?? "(none)")
            WebView(request: URLRequest(url: URL(string: "https://www.google.com")!), navigationState: navigationState)
        }
    }
}

Update, based on comments:

class NavigationState : NSObject, ObservableObject {
    @Published var url : URL?
    let webView = WKWebView()
}

extension NavigationState : WKNavigationDelegate {
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        self.url = webView.url
    }
}

struct WebView : UIViewRepresentable {
    
    let request: URLRequest
    var navigationState : NavigationState
    
    func makeUIView(context: Context) -> WKWebView  {
        let webView = navigationState.webView
        webView.navigationDelegate = navigationState
        webView.load(request)
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) { }
}

struct ContentView: View {
    @StateObject var navigationState = NavigationState()
    
    var body: some View {
        VStack(){
            Text(navigationState.url?.absoluteString ?? "(none)")
            WebView(request: URLRequest(url: URL(string: "https://www.google.com")!), navigationState: navigationState)
            HStack {
                Button("Back") {
                    navigationState.webView.goBack()
                }
                Button("Forward") {
                    navigationState.webView.goForward()
                }
            }
        }
    }
}
jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • The only problem is I have other functions that I use such as goBack goForward. If i dont set webView as a variable, I'm not too sure how I can call goBack() function. I updated my post so you have a better understanding – James Lee Mar 28 '21 at 06:45
  • Just updated my answer based on your new requirements. – jnpdx Mar 28 '21 at 16:09