iOS Development
JavaScript
Mobile App Development
iOS JavaScript Bridge
Cross-platform Integration

iOS JavaScript bridge

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

An iOS JavaScript bridge is the mechanism that lets JavaScript running in a WKWebView talk to native Swift or Objective-C code, and lets native code call back into the web layer. The bridge is useful in hybrid apps, embedded web flows, and cases where web UI and native device features need to cooperate without rewriting everything in one stack.

The Main Pieces of a Bridge

With modern iOS development, the usual bridge is built on top of WKWebView and WKScriptMessageHandler.

The direction of communication is:

  • JavaScript to native through window.webkit.messageHandlers
  • native to JavaScript through evaluateJavaScript

That means the bridge is really a message-passing interface, not a shared-memory interface.

JavaScript to Native

Here is a basic Swift setup that registers a message handler named appBridge:

swift
1import UIKit
2import WebKit
3
4final class ViewController: UIViewController, WKScriptMessageHandler {
5    private var webView: WKWebView!
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9
10        let contentController = WKUserContentController()
11        contentController.add(self, name: "appBridge")
12
13        let config = WKWebViewConfiguration()
14        config.userContentController = contentController
15
16        webView = WKWebView(frame: view.bounds, configuration: config)
17        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
18        view.addSubview(webView)
19
20        let html = """
21        <html>
22          <body>
23            <button onclick="sendMessage()">Send</button>
24            <script>
25              function sendMessage() {
26                window.webkit.messageHandlers.appBridge.postMessage({
27                  action: "log",
28                  value: "Hello from JavaScript"
29                });
30              }
31            </script>
32          </body>
33        </html>
34        """
35
36        webView.loadHTMLString(html, baseURL: nil)
37    }
38
39    func userContentController(_ userContentController: WKUserContentController,
40                               didReceive message: WKScriptMessage) {
41        guard message.name == "appBridge" else { return }
42        print("JS sent:", message.body)
43    }
44}

This is the standard pattern for sending structured messages from the page into native code.

Native to JavaScript

The opposite direction uses evaluateJavaScript:

swift
1webView.evaluateJavaScript("document.body.style.backgroundColor = 'lightyellow';") { result, error in
2    if let error = error {
3        print("JS error:", error)
4    }
5}

You can use this to:

  • trigger page functions
  • inject data
  • update the DOM
  • notify the web layer about native events

For example:

swift
webView.evaluateJavaScript("window.receiveNativeMessage('native says hello')")

as long as the page defines that function on the JavaScript side.

Message Design Matters

Even simple bridges benefit from a consistent message format. A small action-based object is easier to grow than sending raw strings everywhere.

For example:

javascript
1window.webkit.messageHandlers.appBridge.postMessage({
2  action: "openProfile",
3  userId: 42
4});

Then native code can switch on the action field and validate the rest of the payload.

That keeps the bridge readable and reduces the temptation to scatter tiny one-off handlers everywhere.

Security Considerations

The bridge is powerful, so do not treat all JavaScript as trusted automatically. Important precautions include:

  • only load trusted content if the bridge exposes sensitive native behavior
  • validate every incoming payload before acting on it
  • keep the bridge surface small
  • avoid exposing file, token, or device features unnecessarily

If the web content can be influenced by untrusted scripts, an overly permissive bridge can become a serious security problem.

Common Pitfalls

The most common mistake is using WKWebView but forgetting to register the message handler on the WKUserContentController. Without that registration, JavaScript bridge calls fail at runtime.

Another issue is assuming message.body has the exact type you want. It often arrives as a loosely typed Foundation object, so payload validation is necessary.

A third pitfall is injecting JavaScript strings unsafely from native code. If you interpolate user data directly into JavaScript source, quoting bugs and injection issues follow quickly.

Finally, do not forget lifecycle cleanup when long-lived handlers are involved. A retained message handler can contribute to memory-management mistakes if the bridge object graph is not designed carefully.

Summary

  • An iOS JavaScript bridge usually uses WKWebView, WKUserContentController, and WKScriptMessageHandler.
  • JavaScript sends messages to native code through window.webkit.messageHandlers.
  • Native code calls back into the page through evaluateJavaScript.
  • A structured message format makes the bridge easier to maintain.
  • Keep the bridge minimal and validate all incoming data for safety.

Course illustration
Course illustration

All Rights Reserved.