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.

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 ""
        }
    }

}