How to add a navigation bar to WKWebView?

Andrés Quiroga picture Andrés Quiroga · Feb 18, 2015 · Viewed 25.7k times · Source

I'm trying to implement an embedded webView using WKWebView. I have the initial configuration and with the following code I can load a web page into my storyboard.

import UIKit
import WebKit

class WebViewViewController: UIViewController {
    @IBOutlet var containerView: UIView!
    var webView: WKWebView?

    override func loadView() {
        super.loadView()

        self.webView = WKWebView()
        self.view = self.webView!
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        var url = NSURL(string:"http://www.google.com/")
        var req = NSURLRequest(URL:url!)
        self.webView!.loadRequest(req)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

With this, I can see the web content inside my app, but there is not a navigation bar, and I need to allow users to enter a desired url. How can I add a navigation bar like any other web browser?

Answer

Andrés Quiroga picture Andrés Quiroga · Feb 19, 2015

Based on the suggested web link by Devran Cosmo, this is my final view controller code.

import UIKit
import WebKit

class WebViewViewController: UIViewController, UITextFieldDelegate, WKNavigationDelegate {

    var webView: WKWebView
    @IBOutlet weak var barView: UIView!
    @IBOutlet weak var urlField: UITextField!

    // Web Browser navigator
    @IBOutlet weak var backButton: UIBarButtonItem!
    @IBOutlet weak var forwardButton: UIBarButtonItem!
    @IBOutlet weak var reloadButton: UIBarButtonItem!
    @IBOutlet weak var progressView: UIProgressView!

    @IBAction func back(sender: UIBarButtonItem) {
        if (self.webView.canGoBack) {
            self.webView.goBack()
        }
    }

    @IBAction func forward(sender: UIBarButtonItem) {
        if (self.webView.canGoForward) {
            self.webView.goForward()
        }
    }

    required init(coder aDecoder: NSCoder) {
        self.webView = WKWebView(frame: CGRectZero)
        super.init(coder: aDecoder)
        self.webView.navigationDelegate = self
      }

    override func viewWillTransitionToSize(size: CGSize,  withTransitionCoordinator coordinator:     UIViewControllerTransitionCoordinator) {
        barView.frame = CGRect(x:0, y: 0, width: size.width, height: 30)
    }

    // Load user requested url
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        urlField.resignFirstResponder()
        webView.loadRequest(NSURLRequest(URL: NSURL(string: urlField.text)!))
        var list : WKBackForwardList = self.webView.backForwardList

        println("BACK LIST")
        println(list.backList)

        return false
    }

    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context:   UnsafeMutablePointer<()>) {
        if (keyPath == "loading") {
            backButton.enabled = webView.canGoBack
            forwardButton.enabled = webView.canGoForward
        }

        if (keyPath == "estimatedProgress") {
            progressView.hidden = webView.estimatedProgress == 1
            progressView.setProgress(Float(webView.estimatedProgress),  animated: true)
        }
    }

    func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {
        progressView.setProgress(0.0, animated: false)
    }

    func webView(webView: WKWebView!, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError!) {
        let alert = UIAlertController(title: "Error", message:  error.localizedDescription, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .Default,  handler: nil))
        presentViewController(alert, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        barView.frame = CGRect(x:0, y: 0, width: view.frame.width, height: 30)

        // Do any additional setup after loading the view.
        view.insertSubview(webView, belowSubview: progressView)

        webView.setTranslatesAutoresizingMaskIntoConstraints(false)
        let height = NSLayoutConstraint(item: webView, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 1, constant: -44)
        let width = NSLayoutConstraint(item: webView, attribute:    .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1,    constant: 0)
        view.addConstraints([height, width])

        // Disable navigation buttons on first loads
        backButton.enabled = false
        forwardButton.enabled = false

        webView.addObserver(self, forKeyPath: "loading", options: .New, context: nil)
        webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil)

        let url = NSURL(string:"http://www.appcoda.com")
        let request = NSURLRequest(URL:url!)
        webView.loadRequest(request)
    }
}