How To Use WebView In iOS Swift

WebKit.WKWebView class provides functions to implement a micro web browser. It mainly provides three functions that can be used to load and display local Html file data, local binary file data ( such as an image file ), a remote web resource with provided URL (such as http://google.com, file://1.1.1.1/abc.txt), etc. This article will introduce how to use it with examples.

1. WKWebView Main Functions.

  1. loadHTMLString(_ string: String, baseURL: URL?) : Load and display local saved Html file content. The string parameter is the Html file content string. The baseURL parameter value is something like file:///Users/songzhao/Library/……/index.html, it is local Html file URL format, it is used to calculate the relative URLs of the link in the Html page content.
  2. load(_ data: Data, mimeType MIMEType: String, characterEncodingName: String, baseURL: URL) : Load and display a local binary file content with provided mime type and character encoding. The data parameter is a Data type object which contains the binary file content. The baseURL parameter value is something like file:///Users/songzhao/Library/……/apple.png. It is also used to resolve the relative URL of the links in the image document.
  3. load(_ request: URLRequest): Load and display a remote web resource in the web view object. The request parameter contains the remote web resource URL.

2. WKWebView Asynchronously Load Remote Web Resource Multiple Process Phase Functions.

When you use WKWebView class’s load(_ request: URLRequest) function to load a remote web resource, because the process is asynchronous, so you should want to write code to do something during the process in different process phases. Follow the below steps to implement this.

  1. Make a class that implements WebKit.WKNavigationDelegate protocol. In this example, we make the iOS app’s ViewController class to implement the WKNavigationDelegate protocol.
    class ViewController: UIViewController, WKNavigationDelegate
  2. Then set this class’s instance to the WKWebView object’s navigationDelegate property value.
    // Create an instance of WKWebView class.
    var webView: WKWebView! = WKWebView()
    
    // Set this ViewController object as the web view's navigation delegate.
    webView.navigationDelegate = self
  3. Then you can implement below functions of WebKit.WKNavigationDelegate protocol in the class( the ViewController class in this example. ). Each function will be invoked in the related load web resource process phase. You can see below code comments to know each process phase function’s feature.
    /* This function will be invoked when the web view object start load the url page. */
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            
         print("Web view didStartProvisionalNavigation")
       
    }
        
    /* This function will be invoked when the web page content begin to return. */
    
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
    
         print("Web view didCommit")
    
    }
        
    /* This function will be invoked when the page content returned successfully. */
        
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    
         print("Web view didFinish")
    
    }
        
    /* This function will be invoked when the web view object load page failed. */
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    
            print("Web view didFailProvisionalNavigation")
    
        }

3. WKWebView Example.

There are three parts in this example.

  1. A WKWebView object at the top to implement a micro browser.
  2. A UITextField object in the middle to let users input the web page URL. The input URL should be a valid URL, otherwise, it will prompt an alert dialog to let the user input a valid web resource URL.
  3. Three UIButtons at the bottom. Click the first button to load the local Html file in the WKWebView object. Click the second button to load a local image file in the WKWebView object. Click the third button to load the inputted URL page content in the WKWebView object.

  1. If you can not watch the above video, you can see it on URL https://youtu.be/O-YcCPo4wI4
  2. Click the Load Html String button to display an Html file content in the WKWebView. The Html file should be imported into the Xcode project.
  3. Click the Load Data button to display a local image file’s content in the WKWebView. The image file should be imported into the Xcode project also.
  4. Click the Load Request button to load and display the input URL page content in the WKWebView
  5. Below are the Xcode project files. You can see I had import index.html and apple.png files into it. You can read the article How To Add Resource Files Into Xcode Project And iOS App to learn more. Please note you should select Copy items if needed checkbox in the file browse window, then the resource files will be copied into the project.
    :iOSWebViewExample songzhao$ tree ./
    ./
    ├── iOSWebViewExample
    │   ├── apple.png
    │   ├── AppDelegate.swift
    │   ├── Assets.xcassets
    │   │   ├── AppIcon.appiconset
    │   │   │   └── Contents.json
    │   │   └── Contents.json
    │   ├── index.html
    │   ├── Base.lproj
    │   │   ├── LaunchScreen.storyboard
    │   │   └── Main.storyboard
    │   ├── Info.plist
    │   ├── SceneDelegate.swift
    │   └── ViewController.swift
    └── iOSWebViewExample.xcodeproj
        ├── project.pbxproj
        ├── project.xcworkspace
        │   ├── contents.xcworkspacedata
        │   ├── xcshareddata
        │   │   └── IDEWorkspaceChecks.plist
        │   └── xcuserdata
        │       └── songzhao.xcuserdatad
        │           ├── UserInterfaceState.xcuserstate
        │           └── xcdebugger
        │               └── Expressions.xcexplist
        └── xcuserdata
            └── songzhao.xcuserdatad
                ├── xcdebugger
                │   └── Breakpoints_v2.xcbkptlist
                └── xcschemes
                    └── xcschememanagement.plist
    
  6. The WKWebView, UITextField, and three UIButtons are all created in source code. We only need to edit the Xcode project’s ViewController.swift file as below. Please see the code comments for an explanation.
    //
    //  ViewController.swift
    //  iOSWebViewExample
    //
    
    
    import UIKit
    import WebKit
    
    class ViewController: UIViewController, WKNavigationDelegate {
        
        var webView: WKWebView!
        
        var urlTextBox: UITextField!
        
        var loadHtmlStringBtn: UIButton!
        
        var loadDataBtn: UIButton!
        
        var loadRequestBtn: UIButton!
        
        let TAG_LOAD_HTML = 1
        
        let TAG_LOAD_DATA = 2
        
        let TAG_LOAD_REQUEST = 3
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            initWebView()
            
            initUrlTextBox()
            
            initButtons()
        }
    
        /* This function initialize the web view object. */
        func initWebView(){
            
            // Create an instance of WKWebView class.
            webView = WKWebView()
        
            // Set webView's background color.
            webView.backgroundColor = UIColor.green
            
            // Set webView's translatesAutoresizingMaskIntoConstraints property value to false to avoid [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don’t want error.
            webView.translatesAutoresizingMaskIntoConstraints = false
            
            // Set this ViewController object as the web view's navigation delegate.
            webView.navigationDelegate = self
            
            // Add above webView object to the container's root view.
            self.view.addSubview(webView)
            
            // Set webView's layout constraints.
            // Set webView's top anchor distance value.
            let webViewTopAnchor = webView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100)
            webViewTopAnchor.isActive = true
            
            // Center layout the webView in horizontal direction.
            let webViewCenterXAnchor = webView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
            webViewCenterXAnchor.isActive = true
            
            // Layout web view width as 0.8 percent of screen width.
            let webViewWidthAnchor = webView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.8)
            webViewWidthAnchor.isActive = true
            
            // Layout web view height as 0.7 percent of screen height.
            let webViewHeightAnchor = webView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.7)
            webViewHeightAnchor.isActive = true
            
            // The web view object will show the google home page when the app starts.
            loadRequest(urlString: "http://www.google.com")
        }
    
    
        /* This function will initialize the url input text box. */
        func initUrlTextBox(){
            
            // Create a UITextField object.
            urlTextBox = UITextField()
            
            // Set this property value to false to allow set constraints in swift source code later.
            urlTextBox.translatesAutoresizingMaskIntoConstraints = false
            
            // Set the UITextField keyboard type to URL keyboard then when you focus on the input text box, it will prompt URL-related keyboard.
            urlTextBox.keyboardType = UIKeyboardType.URL
            
            // Set the place holder text to tell user what to input.
            urlTextBox.placeholder = "Please input web page url."
            
            // Set background color.
            urlTextBox.backgroundColor = UIColor.green
            
            // Set text box corner radius.
            urlTextBox.layer.cornerRadius = 10
                    
            self.view.addSubview(urlTextBox)
            
            // Set url input text box anchor constraints.
            let urlTextBoxTopAnchor = urlTextBox.topAnchor.constraint(equalTo: self.webView.bottomAnchor, constant: 30)
            urlTextBoxTopAnchor.isActive = true
            
            let urlTextBoxCenterXAnchor = urlTextBox.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
            urlTextBoxCenterXAnchor.isActive = true
            
            let urlTextBoxWidthAnchor = urlTextBox.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.8)
            urlTextBoxWidthAnchor.isActive = true
            
            
        }
        
        /* This function will initialize the three buttons. */
        func initButtons(){
            
            // Init load html string button.
            loadHtmlStringBtn = initButton(title: "Load Html String", tag:TAG_LOAD_HTML)
            // Layout this button left side align to the left side of url input box.
            let loadHtmlStringLeftAnchor = loadHtmlStringBtn.leftAnchor.constraint(equalTo: self.urlTextBox.leftAnchor)
            loadHtmlStringLeftAnchor.isActive = true
    
            
            // Init load data button.
            loadDataBtn = initButton(title: "Load Data", tag: TAG_LOAD_DATA)
            // Layout this button's left side 1 distance from loadHtmlStringBtn's right side.
            let loadDataLeftAnchor = loadDataBtn.leftAnchor.constraint(equalTo: self.loadHtmlStringBtn.rightAnchor, constant: 1)
            loadDataLeftAnchor.isActive = true
                    
            
            // Init load request button.
            loadRequestBtn = initButton(title: "Load Request", tag:TAG_LOAD_REQUEST)
            // Layout this button right side align to the right side of url input box.
            let loadRequestRightAnchor = loadRequestBtn.rightAnchor.constraint(equalTo: self.urlTextBox.rightAnchor)
            loadRequestRightAnchor.isActive = true
            
        }
        
        /* This function will create one button with provided property values. */
        func initButton(title:String, tag:Int) -> UIButton{
            
            // Create a UIButton object.
            let btn:UIButton = UIButton()
            
            // Set button title.
            btn.setTitle(title, for: UIControl.State.normal)
            
            btn.translatesAutoresizingMaskIntoConstraints = false
            
            btn.backgroundColor = UIColor.lightGray
            
            btn.layer.cornerRadius = 10
            
            btn.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
            
            btn.setTitleColor(UIColor.black, for: UIControl.State.normal)
            
            self.view.addSubview(btn)
            
            let btnTopAnchor = btn.topAnchor.constraint(equalTo: self.urlTextBox.bottomAnchor, constant: 10)
            btnTopAnchor.isActive = true
            
            // Set the provide tag value to this button.
            btn.tag = tag
            
            // Set button touch down event process function.
            btn.addTarget(self, action: #selector(processBtnEvent), for: UIControl.Event.touchDown)
            
            return btn
        }
        
        /* This function will process button touch down event. */
        @objc func processBtnEvent(src:UIButton, event:UIControl.Event){
                    
            if(src.tag == TAG_LOAD_HTML)
            {
                loadHtmlString(localHtmlFileName: "index")
            }else if(src.tag == TAG_LOAD_DATA)
            {
                loadData(dataFileName: "apple", dataFileFormat: "png", dataFileMimeType: "image/png")
            }else if(src.tag == TAG_LOAD_REQUEST)
            {
                // Get user input url text string.
                let inputUrl = urlTextBox.text
                
                let isValidUrl = validateUrl(inputUrl: inputUrl!)
                
                if(isValidUrl){
                    loadRequest(urlString: inputUrl!)
                }
            }
        }
        
        /* This function will load a local html file content to the web view to display. */
        func loadHtmlString(localHtmlFileName:String){
            
            /* Below code will return the url of app bundle resource directory where to store app used resource files. It is something like this (file:///Users/songzhao/Library/Developer/CoreSimulator/Devices/DD24399C-5E6F-4271-93BB-D870C73AE454/data/Containers/Data/Application/FB64E9C7-7611-4AB7-AB52-FE7CD3DA5DC8/Documents/) */
            let documentsURL = NSURL(
                fileURLWithPath: NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first!,
              isDirectory: true
            )
            
            print("documentsURL : " + documentsURL.absoluteString!)
            
            /* Get the html file absolute path, it is something like ("/Users/songzhao/Library/Developer/CoreSimulator/Devices/DD24399C-5E6F-4271-93BB-D870C73AE454/data/Containers/Bundle/Application/FBB073B9-8DC9-4B3B-8CEB-57E79AD8CE0A/iOSWebViewExample.app/index.html"). */
            let localHtmlFilePath = Bundle.main.path(forResource: localHtmlFileName, ofType: "html")
            
            print("localHtmlFilePath : " + localHtmlFilePath!)
            
            /* Get the local file url path it is something like ( file:///Users/songzhao/Library/Developer/CoreSimulator/Devices/DD24399C-5E6F-4271-93BB-D870C73AE454/data/Containers/Bundle/Application/FBB073B9-8DC9-4B3B-8CEB-57E79AD8CE0A/iOSWebViewExample.app/index.html ). */
            let localFileUrl = URL.init(fileURLWithPath: localHtmlFilePath!)
            
            print("localFileUrl : " + localFileUrl.absoluteString)
            
            
            do {
                // Get file content and convert to string type data.
                let fileContent = try String(contentsOfFile: localHtmlFilePath!)
                
                // Load the html file content to the web view.
                self.webView.loadHTMLString(fileContent, baseURL: localFileUrl)
                
            } catch let err as Error {
                
                print(err.localizedDescription)
            
            }
    
        }
        
        /* This function will load a binary file (such as an image file) to the web view object to display. */
        func loadData(dataFileName: String, dataFileFormat: String, dataFileMimeType: String){
            
            /* Get the local binary file path. It is something like "/Users/songzhao/Library/Developer/CoreSimulator/Devices/DD24399C-5E6F-4271-93BB-D870C73AE454/data/Containers/Bundle/Application/6CC9D640-D655-4A9B-9616-75DB4ED36B29/iOSWebViewExample.app/apple.png" */
            let localFilePath = Bundle.main.path(forResource: dataFileName, ofType: dataFileFormat)
            
            print(localFilePath)
            
            /* Get the binary file url path. It is something like file:///Users/songzhao/Library/Developer/CoreSimulator/Devices/DD24399C-5E6F-4271-93BB-D870C73AE454/data/Containers/Bundle/Application/6CC9D640-D655-4A9B-9616-75DB4ED36B29/iOSWebViewExample.app/apple.png */
            let localFileUrl = URL.init(fileURLWithPath: localFilePath!)
            
            print(localFileUrl.absoluteString)
        
            do {
                // Get the binary file content data of the file url.
                let fileContent = try Data(contentsOf: localFileUrl)
                
                // Load above binary data to the web view object to display.
                self.webView.load(fileContent, mimeType: dataFileMimeType, characterEncodingName: "", baseURL: localFileUrl)
            } catch let err as Error {
                
                print(err.localizedDescription)
            
            }
        }
        
        /* This function will load a web page by it url address from internet. */
        func loadRequest(urlString:String){
            
            // Set the page url object.
            let urlObj:URL? = URL(string: urlString)
            
            // Create the URLRequest object with above provided url.
            let request:URLRequest = URLRequest(url: urlObj!)
            
            // Load above url in the web view object.
            webView.load(request)
            
            // Allow back and forward navigation with gesture.
            webView.allowsBackForwardNavigationGestures = true
            
        }
        
        /* This function will validate whether the url is valid or invalid. It will return a boolean value. */
        func validateUrl(inputUrl: String) -> Bool{
            
            // Make the url string lowercased.
            var inputUrl = inputUrl.lowercased()
            
            // Trim the white space and new line character from the url string.
            inputUrl = inputUrl.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
            
            // If the url string is empty and it do not start with http:// and https:// then prompt an alert dialog.
            if(inputUrl.isEmpty == true || (inputUrl.starts(with: "http://") == false && inputUrl.starts(with: "https://") == false))
            {
                // Create UIAlertController object with special alert message.
                let alertController:UIAlertController = UIAlertController(title: "Message", message: "Please input a valid url address started with http:// or https://", preferredStyle: UIAlertController.Style.alert)
                
                // Create tge UIAlertAction object.
                let alertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler:nil)
                
                // Add the UIAlertAction object to the UIAlertController object.
                alertController.addAction(alertAction)
                
                // Present the alert dialog.
                present(alertController, animated: true, completion: nil)
                
                return false
    
            }else{
                return true
            }
        }
        
        /* This function will be invoked when the web view object start load the url page. */
        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            print("Web view didStartProvisionalNavigation")
        }
        
        /* This function will be invoked when the web page content begin to return. */
        func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
            print("Web view didCommit")
        }
        
        /* This functio will be invoked when the page content returned successfully. */
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            print("Web view didFinish")
        }
        
        /* This function will be invoked when the web view object load page failed. */
        func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
            print("Web view didFailProvisionalNavigation")
        }
    }
    

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.