Working with UIWebView in Swift

In a previous tutorial, I wrote about UIWebView and UIActivityIndicator and how to use them to load a url. The article has helped a lot of my sweet readers, so I decided to write this quick tutorial to enhance the project, and also upgrade it to Swift.

The final app you are going to develop here will provide a search bar where you can type the url and load it using UIWebView, similar behaviour as the Safari mobile browser app.

Working with UIWebView in Swift

To start out, download the starter project here.

Open the project in Xcode and select Main.storyboard from the Project navigator view. The view has 3 main objects: UISearchBar in the top view, UIWebView filling all the rest of the screen, and a centered UIActivityIndicator. I set up some Auto Layout constraints to organise the objects positions and frames for different screen sizes and orientations.

All objects added in storyboard are already hooked up to the code and their delegates are already set to the view controller.

Hook up objects to the code

Moving to the code, the first thing to do is to retrieve the typed url from the search bar.

Select the ViewController.swift file to open it in the editor.

Place the following code before the closing bracket of the class:

func searchBarSearchButtonClicked(searchBar: UISearchBar){
     searchBar.resignFirstResponder()
     let url:NSURL = NSURL(string: "http://\(searchBar.text)")!
     let request = NSURLRequest(URL: url)
     webView.loadRequest(request)
}

The method above is a UISearchBarDelegate method which gets called each time you press the search button on your phone keyboard (or the return key if you are using the simulator).

The keyboard is dismissed, the typed string is then retrieved using the text property of the search bar and appended to the “http://” string to complete the url format.

An NSURLRequest object is constructed using the url object and passed to the loadRequest API of the web view that starts the load operation immediately.

Run the project and type in some url, then hit the search button of the keyboard (or the return key if you use the simulator).

Cool, the url is loaded, yet the activity indicator is neither animating, nor dismissing after the web view has completed the load operation.

You are missing two delegate methods to tell you when does the web view starts and when does it finish loading the url.

Place the following methods implementations following the precedent code:

func webViewDidStartLoad(webView: UIWebView){
   activityIndicator.startAnimating()
}

func webViewDidFinishLoad(webView: UIWebView){
   activityIndicator.stopAnimating()
   activityIndicator.hidden = true
}

The methods above are notifying the controller each time a url is starting and finishing loading, those two methods are the right place to start/stop animating the activity indicator object accordingly.

Run the project, type in a url and press the return button of the keyboard.

So far so good, the last thing to do is to hide the activity indicator object when the app starts, as long as no url request is running, there is no need to show the activity indicator.

Locate the viewDidLoad method and place the following statement right after the super.viewDidLoad() call:

activityIndicator.hidden = true

Also, locate the webViewDidStartLoad delegate method you implemented previously, and add the following call before the startAnimating() call:

activityIndicator.hidden = false

Before you finish up, let’s add an error handling to catch a url loading failure, UIWebView has a convenient delegate method to handle such case. Go ahead and copy the following method before the closing bracket of the class:

func webView(webView: UIWebView,
        didFailLoadWithError error: NSError){
    let alert:UIAlertController = UIAlertController(title: "Error", message: "\(error)", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert, animated: true, completion: nil)
    activityIndicator.hidden = true
}

As you may notice, UIAlertController is the convenient class to use in order to show alerts and action sheets. This class replaces the UIAlertView that is now deprecated.

The alert object you defined above is a stand-alone view controller (UIAlertController is a subclass of UIViewController), which explains why you use self.presentViewController API to show the alert on the screen.

That’s it, run the project and test your work 🙂

As usual, you can download the final project here. This tutorial is an updated version of a previous article written in Objective-C.

Feel free to leave a comment below, I am always open to your suggestions and questions.

Malek
iOS developer with over than 11 years of extensive experience working on several projects with different sized startups and corporates.

7 Comments

  1. Awesome post, and I really like that you included some error handling, so many tuts skip that when in actuality it’s just as important. Hopefully this tutorial helps out just as many readers as before, but with SafariViewController in iOS9 hopefully we can leave UIWebView for just those that want to implement their own custom page!

  2. Hi Michael, million thanks for your feedback. BTW, I am planning to write about SFSafariViewController soon 🙂

  3. These tutorials are fantastic! I have searched tirelessly and have not found any information about using UICollectionview to show local pdf files instead of images. If you ever feel like making a tutorial to tackle that, i would be most grateful. Again, wonderful job on all of these!

  4. Hi James, UICollectionView is also on my to-do list of tutorials. Stay tuned and subscribe to the blog to get notified 😉

Comments are closed.