Inject JavaScript into WKWebView

In Swift, it is possible to inject a JavaScript code into a WKWebView and execute it from your app. The below code example demonstrates how to:

  • Load HTML file from a local file,
  • Load JavaScript code from a local file,
  • Create WKUserScript object,
  • Inject JavaScript into an HTML document.

If you are interested in video lessons on how to write Unit tests and UI tests to test your Swift mobile app, check out this page: Unit Testing Swift Mobile App

Load HTML File From App Bundle

let myProjectBundle:Bundle = Bundle.main
let myUrl = myProjectBundle.url(forResource: "my-html-file", withExtension: "html")!
myWebView.loadFileURL(myUrl,allowingReadAccessTo: myUrl)

Load JavaScript Code From a Local File

The below code example is a function which you can add to your Swift file and call to load the content of a demo-script.js file.

func getMyJavaScript() -> String {
       if let filepath = Bundle.main.path(forResource: "demo-script", ofType: "js") {
           do {
               return try String(contentsOfFile: filepath)
           } catch {
               return ""
           }
       } else {
          return ""
       }
   }

where:

demo-script – is the name of a file. Notice that there is no need to specify file extension here.
js – The demo-script file extension.

Inject JavaScript to WKWebView with WKUserScript

var myWebView: WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()
   
    let config = WKWebViewConfiguration()
    let js = getMyJavaScript()
    let script = WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
    
    config.userContentController.addUserScript(script)
    config.userContentController.add(self, name: "clickListener")
    
    myWebView = WKWebView(frame: view.bounds, configuration: config)

    myWebView.uiDelegate = self
    myWebView.navigationDelegate = self

    view.addSubview(myWebView!)
}

where:

getMyJavaScript() – is a function that loads JavaScript from a local file. The source code of this function is also on this page.

Complete Example

import UIKit
import WebKit
import Firebase

class MyWebViewViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
    
    var myWebView: WKWebView!
    
     override func viewDidLoad() {
        super.viewDidLoad()
        
        let config = WKWebViewConfiguration()
        let js = getMyJavaScript()
        let script = WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
        
        config.userContentController.addUserScript(script)
        config.userContentController.add(self, name: "clickListener")
        
        myWebView = WKWebView(frame: view.bounds, configuration: config)
        myWebView.uiDelegate = self
        myWebView.navigationDelegate = self

        view.addSubview(myWebView!)
 
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        let myProjectBundle:Bundle = Bundle.main
        
        let myUrl = myProjectBundle.url(forResource: "my-html-file", withExtension: "html")!
        myWebView.loadFileURL(myUrl,allowingReadAccessTo: myUrl)
        
        //let url = URL(string: "https://appsdeveloperblog.com")!
        //myWebView.load(URLRequest(url: url))
 
    }

    func getMyJavaScript() -> String {
        if let filepath = Bundle.main.path(forResource: "demo-script", ofType: "js") {
            do {
                return try String(contentsOfFile: filepath)
            } catch {
                return ""
            }
        } else {
           return ""
        }
    }

}