Swift Swift: Using UIWebViews in Swift

[Updated to Swift2.0/iOS9 — 10/17/15 SJL]
There are times we need formatted content. There are also times we need to access content on the web. The UIWebView is a very useful view for both. In this week’s lesson we’ll explore how to use this view in a variety of applications.

One warning: Since this is about web browsers. I will be using HTML/CSS. Since this lesson is about Swift and Xcode and not a web design I’ll present this code as-is. If you do not know any HTML there are more than a few courses available to you to get you up to speed.

Set Up the Scene

Open a new single view project called SwiftWebView. Make this project Universal instead of our usual iPhone. This project will work on both iPads and iPhones. Go to the storyboard. Drag a Web View and a Tool Bar onto the storyboard. This application will use auto layout. Start by aligning the toolbar with the blue lines on the storyboard at the top, then align the web view underneath it to take up the rest of the space on the view. Add four bar buttons the the toolbar and label them as below. Use a few bar spacers to space them out. When done it should look something like this:
Screenshot 2014-10-27 07.18.28

Now click the toolbar and the pin Screenshot 2014-10-27 07.25.10 button on the storyboard. Click on the top left and right i-beams and then set the pop up to this, ignoring the bottom constraint:

2015-10-17_20-37-55

Do the same for the web view and set it to this:

2015-10-17_20-37-55

Once done, you may get warnings from Xcode that the frames will not be the same a run time. If so, first click one of the objects on the story board, then click the Screenshot 2014-10-28 17.46.59 and select Update Frames to refresh the frame. Doe the same for the other object if there are still warnings.

Wire Up the Project

Open the assistant editor, and control drag the web view into the ViewController class. Name the outlet myWebview.

Add four actions, one for each of the bar buttons as helloPizza, makeAppPie, back and forward . When done, your code should look like this:

class ViewController: UIViewController {

    @IBOutlet weak var myWebView: UIWebView!
//Navigation in a web view
    @IBAction func back(sender: AnyObject) {

    }

    @IBAction func forward(sender: AnyObject) {

    }

// Go to a internal or external html page
    @IBAction func makeAppPie(sender: AnyObject) {

    }

    @IBAction func helloPizza(sender: UIBarButtonItem) {

    }

    override func viewDidLoad() {

    }

}

A Web View From a String

There are several ways to use a web view. Before attributed strings, this was the only way to get formatted text. The developer would write a string of text in HTML and send it to a UIWebview using the method loadHTMLString. Change the viewDidLoad method to this:

overridefuncviewDidLoad() {
        super.viewDidLoad()
        letmyHTMLString:String! = "
<h1>Hello Pizza!</h1>

"
        myWebView.loadHTMLString(myHTMLString, baseURL: nil)
    }

Line 3 makes a optional string, since the loadHTMString method requires one. Line 4 loads the string, and has a second parameter baseURL, which sets the base URL path for the HTML. Usually we set this to nil but if you had files you wanted to load like images or a style sheet, this would give the default path for the files.
Build and run:

Screenshot 2014-10-28 06.24.09

That was pretty boring, so let’s add some more HTML code, replace the string with this, all without a line break.

letmyHTMLString:String! = "
<h1 style=\"font-family: Helvetica\">Hello Pizza</h1>

Tap the buttons above to see <strong>some cool stuff</strong> with <code>UIWebView</code>

<img src=\"https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg\">"

You’ll notice a few places where we used the Quote escape sequence \". We need to add quotes in a few places and a backslash followed by a quote allows us to do so within a string. Build and Run. That is a little better:

Screenshot 2014-10-28 18.22.24

A Web View and CSS From Files

Trying to make something formatted from a string is not easy. Our work would be easier if we had the HTML in a separate file. Even better would be an external style sheet. Tap Command-N on the keyboard or File>New>File… from the drop-down menu to make a new file. Make a blank file by going to Other under iOS and Empty.
Screenshot 2014-10-28 05.51.55
Click next and then name the file myHTML.html. Save the file. In the blank file add the following code:

<!DOCTYPE html>
<html>
<head>
    <title>Hello Pizza! Home</title>
    <link rel="stylesheet" href="myCSS.css" type="text/css">
</head>
<body>
<!-- Site navigation menu -->

<div class="navbar">
    <a href="index.html">Home</a>
    <a href="musings.html">Toppings</a>
    <a href="town.html">Crust</a>
    <a href="links.html">Ovens</a>
</div>


<div class="content">
    <!-- Main content -->

<h1>Hello Pizza!</h1>



This is a site for the love of all things pizza!

    


But we are not just pizza, we are with anything on a flatbread. So look around and you will find naan, flatbreads, pitas and tortilla related stuff too!!!

    


If that is not enough, check our sister site <a href="pie">Hello Pie</a>

    
    <img src="https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg" alt="" />
    <!-- Sign and date the page, it's only polite! -->
</div>


<address>Made 16 October 2015
    by makeapppie.com.</address>

</body>

Back in the ViewController.swift file change the helloPizza method to this:

    @IBAction func helloPizza(sender: UIBarButtonItem) {
        let myURL = NSBundle.mainBundle().URLForResource("myHtml", withExtension: "html")
        let requestObj = NSURLRequest(URL: myURL!)
        myWebView.loadRequest(requestObj)
    }

Line 2 creates a url for myHTML.html from what is called the main bundle. The main bundle is the directory we place all of our code files in XCode for a specific project. The main bundle changes location depending on the device. Instead of giving a literal path, we use this relative indicator. Line 3 creates an NSURLRequest, an object we feed into the loadRequest method in line 4. The loadRequest loads the HTML code into the UIWebView. Build and run this. Click the Pizza button and you get this:
Screenshot 2014-10-28 06.21.42
This view is not that pretty, but we can add some CSS to clean it up a bit. Create another blank file as you did before, named myCSS.css and add the following to the new file:

body {
    color: #eeeeee;
    background: #a0a088;
    font-family:Helvetica}
h1 {
    color: #dd1111;
    font-family:Chalkduster;
    font-size: 18pt}
a{
    font-family:Helvetica;
    font-weight: bold;
    color: #ffffaa;
    text-decoration:none;
    padding-left: 5px;
}
img{
    padding-left:0;
    max-width: 90%;
    max-height: 90%;
    box-shadow: 3px 3px 3px 0px #202020
}
.navbar {
    background-color: #000000;
    color: white;
    position: absolute;
    top: 0em;
    left: 0em;
    width: 100% }
.content{
    padding-left: 1em;
    padding-top: 1em;
}

The HTML code  in myHtml.Html

<link rel="stylesheet" href="myCss.css" type="text/css">

assumes that the baseURL is the bundle. Build and run and we get a better formatted web view:
Screenshot 2014-10-28 06.22.15

A Web View From a Website

Many times we will want to pull something directly from the web. Instead of getting our url from a bundle, we just type it explicitly to a web address. For example, change the makeAppPie code to this:

    @IBAction func makeAppPie(sender: AnyObject) {
        let url = NSURL(string: "http://makeapppie.com")
        let requestObj = NSURLRequest(URL: url!)
        myWebView.loadRequest(requestObj)
    }

Build and run, and tap the AppPie button. You will get an error in the error console, and no web page.
2015-10-17 12:57:28.540 SwiftWebView[22360:1181188] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

Starting in iOS9 Apple added extra security to NSURLRequest. In another post I’ll describe this in detail. We can shut down this security with a entry in the plist.info file. IN the Navigator, right-click on plist.info. Select Open As > Source Code.

2015-10-17_12-29-43

 

In the XML code that appears add this just under the first tag:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key><true/>
    </dict>

Build and run again. Press AppPie. Now we get the web page.

2015-10-17_20-33-36

 

It may take a while, particularly if using the simulator for the web page to display. This is one of those places where you might want to avoid any other processing while running your webview.

Web View Navigation

A problem with what we’ve got so far is navigation. I can go to links on MakeAppPie, and dive into an article, but I can t go backwards. UIWebview has methods to handle that. Change the back and forward button actions to this:

//code to do navigation in the web view
    @IBAction func back(sender: AnyObject) {
        if myWebView.canGoBack{
            myWebView.goBack()
        }
    }

    @IBAction func forward(sender: AnyObject) {
        if myWebView.canGoForward{
            myWebView.goForward()
        }
    }

In each case we check the property canGoForward or canGoBack. If we can go forward or back, we then use the method to do so. Build and run we can now use the back and forward buttons to navigate the web browser when there is a page to go forward or backward to.

The Whole Code

//
//  ViewController.swift
//  SwiftWebView
//
//  Created by Steven Lipton on 10/16/15.
//  Copyright © 2015 Steven Lipton. All rights reserved.
//

import UIKit

class ViewController:UIViewController {
    
    @IBOutlet weak var busyindicator:UIActivityIndicatorView!
    
    @IBOutlet weak var myWebView: UIWebView!
    //code to do navigation in the web view
    @IBAction func back(sender:AnyObject) {
    if myWebView.canGoBack{
    myWebView.goBack()
    }
    }
    
    @IBAction func forward(sender:AnyObject) {
    if myWebView.canGoForward{
    myWebView.goForward()
    }
    }
    // go to a internal or external html page
    /* be sure to add this to the info.plist
    <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key><true/>
        </dict>

    */
    @IBAction func makeAppPie(sender:AnyObject) {
        let url = NSURL(string: "https://makeapppie.com/2014/10/28/swift-swift-using-uiwebviews-in-swift/)
        let requestObj = NSURLRequest(URL:url!)
        myWebView.loadRequest(requestObj)
    }
    
    
    
    @IBAction func helloPizza(sender:UIBarButtonItem) {
        let myURL = NSBundle.mainBundle().URLForResource("myHtml",withExtension: "html")
        let requestObj = NSURLRequest(URL:myURL!)
        myWebView.loadRequest(requestObj)
    }
    
    override func viewDidLoad() {
     super.viewDidLoad()
     //let myHTMLString:String! = "</pre>
<h1>Hello Pizza!</h1>
<pre>"
       let myHTMLString : String! = "
<h1 style=\"font-family: Helvetica\">Hello Pizza</h1>

Tap the buttons above to see <strong>some cool stuff</strong> with <code>UIWebView</code>

<img src=\"https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg\">"
        myWebView.loadHTMLString(myHTMLString, baseURL: nil)
    }

}

myHtml.html

<!DOCTYPE html>
<html>
<head>
    <title>Hello Pizza! Home</title>
    <link rel="stylesheet" href="myCSS.css" type="text/css">
</head>
<body>
<!-- Site navigation menu -->

<div class="navbar">
    <a href="index.html">Home</a>
    <a href="musings.html">Toppings</a>
    <a href="town.html">Crust</a>
    <a href="links.html">Ovens</a>
</div>


<div class="content">
    <!-- Main content -->

<h1>Hello Pizza!</h1>



This is a site for the love of all things pizza!

    


But we are not just pizza, we are with anything on a flatbread. So look around and you will find naan, flatbreads, pitas and tortilla related stuff too!!!

    


If that is not enough, check our sister site <a href="pie">Hello Pie</a>

    
    <img src="https://apppie.files.wordpress.com/2014/09/photo-sep-14-7-40-59-pm_small1.jpg" alt="" />
    <!-- Sign and date the page, it's only polite! -->
</div>


<address>Made 16 October 2015
    by makeapppie.com.</address>

</body>

myCSS.css

body {
    color: #eeeeee;
    background: #a0a088;
    font-family:Helvetica}
h1 {
    color: #dd1111;
    font-family:Chalkduster;
    font-size: 18pt}
a{
    font-family:Helvetica;
    font-weight: bold;
    color: #ffffaa;
    text-decoration:none;
    padding-left: 5px;
}
img{
    padding-left:0;
    max-width: 90%;
    max-height: 90%;
    box-shadow: 3px 3px 3px 0px #202020
}
.navbar {
    background-color: #000000;
    color: white;
    position: absolute;
    top: 0em;
    left: 0em;
    width: 100% }
.content{
    padding-left: 1em;
    padding-top: 1em;
}

13 Replies to “Swift Swift: Using UIWebViews in Swift”

    1. func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

      if navigationType == UIWebViewNavigationType.LinkClicked{
      UIApplication.sharedApplication().openURL(request.URL!)
      return false
      }
      return true
      }

  1. Hi it’s very helpful post to me. But in my xcode simulator i can not show/scroll the whole page. Only the upper portion can be loaded/scrolled. What should i do?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s