'WKWebView not showing Navigation Bar

I have a view in SwiftUI that shows a WKWebView which is passed to the main ContentView using the UIViewControllerRepresentable class, implemented following the instructions from Paul Huson's 'Creating a simple browser with WKWebView. However, when I load the app in the simulator, there doesn't seem to be a Navigation Bar.

Here is my code:

The ContentView and BrowserView

struct ContentView: View {

    let browserView = BrowserView()
    var body: some View {
        browserView
    }
}

struct BrowserView: UIViewControllerRepresentable {

    func makeUIViewController(context: UIViewControllerRepresentableContext<BrowserView>) -> WKBrowser {
        let browser = WKBrowser()
        return browser
    }

    func updateUIViewController(_ uiViewController: WKBrowser, context: UIViewControllerRepresentableContext<BrowserView>) {
        // Empty
    }

}

The WKBrowser class

class WKBrowser: UIViewController, WKNavigationDelegate {

    var webView: WKWebView!

    var webURL = URL(string: "https://www.hackingwithswift.com")!

    override func loadView() {
        webView = WKWebView()
        webView?.navigationDelegate = self
        self.view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.load(URLRequest(url: webURL))
    }
}

The result:

The WKWebView

Compared to the WKWebView from the tutorial which has the Navigation Bar and looks like this:

enter image description here

What do I have to add or edit in order to ensure the Navigation Bar appears?

Edit 05/19/2020:

I'd like to add items to the navigation bar via the navigationItem.rightBarItem function, added to the viewDidLoad, like so:

override func viewDidLoad() {
    super.viewDidLoad()
    webView.load(URLRequest(url: webURL))
    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Open", style: .plain, target: self, action: #selector(someFunction)
}

@objc func someFunction(){
    // Do something
}

Optimally, the result would look something similar to SFSafariViewController:

enter image description here

But when when I wrap the UIViewRepresentable class in a NavigationView, these items are not added to the Navigation Bar that appears, and I instead get this:

enter image description here



Solution 1:[1]

If you want to work with navigation bar in UIKit part then you need to wrap your UIKit browser in UINavigationController, like below

Tested with Xcode 11.4 / iOS 13.4

demo

struct BrowserView: UIViewControllerRepresentable {

    func makeUIViewController(context: Context) -> UINavigationController {
        let browser = WKBrowser()
        return UINavigationController(rootViewController: browser)
    }

    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
        // Empty
    }

}

Solution 2:[2]

actually you have a simpler way.

first wrap a web view:

struct WebView: UIViewRepresentable {
    var url: URL
    
    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }

    func updateUIView(_ webView: WKWebView, context: Context) {
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

then you can put the WebView into a VStack and this will make the UIView stuff like a SwiftUI component. and everything work fine!

   var body: some View {
        NavigationView {
            VStack {
                WebView(url: someURL)
            }
            .toolbar {
               // buttons here ....
            }
        }
   }

Great!

Solution 3:[3]

I'm using Xcode 14 while following the same tutorial. Embedding in Navigation Controller solved the problem without changing any of the code from the tutorial.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Asperi
Solution 2 losiu
Solution 3 kravb