Skip to content
Star

Using it in Swift

The Swift runtime is written in Swift. It receives messages from WKWebView, runs request/command handlers, and emits events to the web app. TypeScript is used only to analyze the contract and generate Swift code.

Install

Add the repository root Package.swift as a Swift Package. During development, select this repository with Xcode's Add Local Package. After a release tag is available, use the repository URL as a Swift Package dependency.

Generate Swift code from the project containing the contract and add it to the iOS target.

bash
npx webview-bridge-kit-gen \
  --contract ./bridge-contract.ts \
  --lang swift \
  --out ./ios/BridgeTypes.swift

The output contains Codable DTOs, a BridgeHandlers protocol, NativeBridge.bind, and type-safe event functions.

Wire WKWebView

swift
import UIKit
import WebKit
import WebViewBridgeKit

final class AppBridgeHandlers: BridgeHandlers {
    func kakaoLogin() async throws -> KakaoLoginResponse {
        KakaoLoginResponse(accessToken: try await login(), expiresIn: nil, nickname: nil)
    }

    func sendLogs(_ payload: SendLogsPayload) async throws {
        logger.write(payload.lines)
    }

    func openCamera() async throws {
        // Navigate to the camera.
    }
}

@MainActor
final class WebViewController: UIViewController {
    private let webView = WKWebView()
    private var bridge: NativeBridge?

    override func viewDidLoad() {
        super.viewDidLoad()

        let transport = WKWebViewTransport(webView: webView)
        let bridge = NativeBridge(transport: transport)
        bridge.bind(AppBridgeHandlers())
        self.bridge = bridge
    }

    func photoTaken(_ payload: PhotoTakenPayload) throws {
        try bridge?.emitPhotoTaken(payload)
    }

    deinit {
        bridge?.dispose()
    }
}

Keep NativeBridge alive for the screen's lifetime. dispose() removes the script message handler and releases registered handlers.

The default web transport automatically detects window.webkit.messageHandlers.webviewBridgeKit; no JavaScript shim is needed. If you choose another handler name, pass a custom web Transport.

Errors

  • An unregistered request returns an UNKNOWN_MESSAGE response.
  • A payload that cannot decode into the generated type returns VALIDATION_FAILED.
  • BridgeHandlerError preserves its custom code and message.
  • Other handler failures return HANDLER_ERROR.

Load trusted content only

Only load app-controlled HTTPS origins or bundled content in a WebView that exposes native functionality. Do not navigate the same WebView to arbitrary external pages.