Introduction:

  • In this article, we will discuss how to connect a Swift Web view to JavaScript and provide an example. In general, to inject a web view page into a Swift project, we use the WebView component.
  • In the example in this article, we want to send token values to a JavaScript page and use values such as some String(title) from JavaScript in Swift.

Section 1: Setting Up WebKit in Swift

  • Begin by importing the WebKit framework, a vital step in Swift-JavaScript integration.
  • Create two essential objects: WKPreferences and WKWebViewConfiguration to enable JavaScript interactions.
  • Clarify the importance of enabling JavaScript in WebView preferences.
import WebKit
 
class WebViewComponent: UIViewController {

let preferences = WKPreferences()
let config = WKWebViewConfiguration()

override func viewDidLoad() {
super.viewDidLoad()

preferences.javaScriptEnabled = true
preferences.javaScriptCanOpenWindowsAutomatically = true

config.userContentController.add(self, name: "title")

config.preferences = preferencesand
  }

}

Section 2: Injecting Swift into JavaScript

  • Here, we want to send values like tokens to JavaScript using the example below.
  • Please note that the same name(IOSInterface) should be present in JavaScript as well.

in Swift:

let scriptJS = """
  const IOSInterface = {
    getToken() {
      return '{\"token\":\"\(token)\"}';
    },
  };
"""

in JS:

const tokenModelJson = IOSInterface.getToken()

Section 3: Integrating WKWebView into Your App

  • To fully integrate WKWebView into your iOS application, follow these steps:
  1. Create a WKWebView instance.
  2. Set the UI delegate and navigation delegate.
  3. Add the WKWebView to your view.
  4. Set up constraints for proper layout.
  5. Customize the user agent for web view.(if you neede)
  6. Load the desired URL.
let script = WKUserScript(source: scriptJS, injectionTime: .atDocumentStart, forMainFrameOnly: true)
config.userContentController.addUserScript(script)

webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.height), configuration: config)

webView.uiDelegate = self
webView.navigationDelegate = self

self.view.addSubview(self.webView)
self.webView.translatesAutoresizingMaskIntoConstraints = false

// Set constraints
self.webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
self.webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true
self.webView.topAnchor.constraint(equalTo: self.headerView.bottomAnchor, constant: 0).isActive = true
self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true

self.webView.customUserAgent = //set user agent if you used

let urlRequest = URLRequest(url: url)

self.webView.load(urlRequest)

Section 4: Handling Callbacks from JavaScript

  • To efficiently manage callback functions, we'll introduce the use of extensions. We'll then implement key methods for handling JavaScript callbacks.
extension WebViewComponent: WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate {

func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {}

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {}
}

Section 5: Receiving Requests from JavaScript

  • We'll explore how to use userContentController to receive requests from JavaScript and provide code examples for handling different request types.
  • After a call back from JS this method calls with a message by name and body like this code:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    let name = message.name
    let body = message.body
    
    // Handle various JavaScript requests
    if name == "close" {
        dismiss(animated: true)
    } else if name == "title" {
        titleLabel.text = (body as! String)
    }
}

Section 6: Displaying JavaScript Alerts in Swift

  • We'll delve into the process of handling JavaScript alerts in Swift using runJavaScriptAlertPanelWithMessage and provide code samples for presenting these alerts in your iOS app.
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
    let alertController = UIAlertController(title: message, message: nil, preferredStyle: .alert)
    
    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) { _ in
        completionHandler()
    })
    
    self.present(alertController, animated: true, completion: nil)
}

Section 7: JavaScript Interactions from the JS Side

  • In this section, we'll briefly explain how to send messages from JavaScript to Swift using the window.webkit.messageHandlers API. We'll also provide examples of sending data from JavaScript to Swift.
  • we can send URLs, text, and others like that
// Examples of sending data from JS to Swift
window.webkit.messageHandlers.title.postMessage(some text)

Conclusion:

  • In conclusion, this article has provided a comprehensive guide to seamlessly integrate Swift with JavaScript using WebKit. We've covered essential steps and techniques for effective cross-language communication in web applications. We encourage readers to explore these methods and apply them to their own projects.