### Setup WKWebView Javascript Bridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/errors.md Call this setup function to initialize the bridge. It takes a callback that is executed once the bridge is ready. ```javascript setupWKWebViewJavascriptBridge(function(bridge) { console.log('Bridge ready'); }); ``` -------------------------------- ### Use Initialized JavaScript Bridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Example of how to use the bridge object after it has been successfully set up. ```javascript setupWKWebViewJavascriptBridge(function(bridge) { console.log('Bridge ready!'); // Now you can use bridge.registerHandler, bridge.callHandler }); ``` -------------------------------- ### Setup WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/WKWebViewJavascriptBridgeDemo/Demo.html Initializes the WKWebViewJavascriptBridge. It ensures the bridge is ready before proceeding and handles the callback mechanism for when the bridge becomes available. ```javascript function setupWKWebViewJavascriptBridge(callback) { if (window.WKWebViewJavascriptBridge) { return callback(WKWebViewJavascriptBridge); } if (window.WKWVJBCallbacks) { return window.WKWVJBCallbacks.push(callback); } window.WKWVJBCallbacks = [callback]; window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null) } ``` -------------------------------- ### Minimal WKWebViewJavascriptBridge Setup Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md This snippet shows the basic initialization of WKWebViewJavascriptBridge within a ViewController. It sets up a WKWebView and then initializes the bridge with it. Load a URL to see it in action. ```swift import UIKit import WebKit import WKWebViewJavascriptBridge class ViewController: UIViewController { var webView: WKWebView! var bridge: WKWebViewJavascriptBridge! override func viewDidLoad() { super.viewDidLoad() webView = WKWebView(frame: view.bounds) view.addSubview(webView) bridge = WKWebViewJavascriptBridge(webView: webView) if let url = URL(string: "https://example.com") { webView.load(URLRequest(url: url)) } } } ``` -------------------------------- ### Setup WKWebViewJavascriptBridge in JavaScript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/README.md Include this JavaScript function in your web content to set up the bridge. It handles the initial connection and callback registration. ```javascript function setupWKWebViewJavascriptBridge(callback) { if (window.WKWebViewJavascriptBridge) { return callback(WKWebViewJavascriptBridge); } if (window.WKWVJBCallbacks) { return window.WKWVJBCallbacks.push(callback); } window.WKWVJBCallbacks = [callback]; window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null) } ``` -------------------------------- ### Example: Call Native Handler for Current Time Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Shows calling a native handler to get the current server time, using a callback but no explicit data. ```javascript // Call with just a callback (data is null) bridge.callHandler('getCurrentTime', function(timeData) { console.log('Server time:', timeData.timestamp); }); ``` -------------------------------- ### Example Message (JavaScript to Native - Response) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Shows an example of a message sent from JavaScript back to native code, typically as a response to a previous native call. It includes the response ID and response data. ```swift let response: WKWebViewJavascriptBridgeBase.Message = [ "responseID": "native_iOS_cb_1", "responseData": ["result": "success"] ] ``` -------------------------------- ### Full ViewController Integration with WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md A comprehensive example showing how to set up WKWebView, WKWebViewJavascriptBridge, register native handlers, and load HTML content with JavaScript interactions. ```swift class HybridViewController: UIViewController { var webView: WKWebView! var bridge: WKWebViewJavascriptBridge! var userData: [String: Any]? override func viewDidLoad() { super.viewDidLoad() setupWebView() setupBridge() } private func setupWebView() { let config = WKWebViewConfiguration() config.defaultWebpagePreferences.allowsContentJavaScript = true webView = WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) } private func setupBridge() { bridge = WKWebViewJavascriptBridge(webView: webView) #if DEBUG bridge.isLogEnable = true #endif registerHandlers() loadWebContent() } private func registerHandlers() { // Get device info bridge.register(handlerName: "getDeviceInfo") { _, callback in callback?([ "model": UIDevice.current.model, "osVersion": UIDevice.current.systemVersion, "orientation": UIDevice.current.orientation.rawValue ]) } // Get user data bridge.register(handlerName: "getUserData") { _, callback in callback?(self.userData ?? [:]) } // Update user data bridge.register(handlerName: "updateUser") { [weak self] params, callback in guard let self = self, let params = params else { callback?(["error": "Invalid data"]) return } self.userData = params callback?(["success": true]) } // Log from JS bridge.register(handlerName: "log") { params, _ in if let message = params?["message"] as? String { print("[JS] \(message)") } } } private func loadWebContent() { let htmlString = """

Hybrid App

""" webView.loadHTMLString(htmlString, baseURL: nil) } } ``` -------------------------------- ### Example: Call Native Handler for Analytics Logging Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Illustrates calling a native handler to log analytics events, sending data but not expecting a response. ```javascript // Call with data, no response bridge.callHandler('logAnalytics', { event: 'page_viewed' }); ``` -------------------------------- ### Example: Call Native Handler for User Data Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Demonstrates calling a native handler to retrieve user data, including sending specific data and handling the response. ```javascript // Call with data and callback bridge.callHandler('getUserData', { id: 123 }, function(userData) { console.log('User:', userData.name); }); ``` -------------------------------- ### Example Swift Dictionary for Serialization Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/message-protocol.md An example of a Swift dictionary structure that can be serialized into a JSON string for communication. ```swift let message: [String: Any] = [ "handlerName": "test", "data": ["key": "value"], "callbackID": "native_iOS_cb_1" ] // Produces: {"handlerName":"test","data":{"key":"value"},"callbackID":"native_iOS_cb_1"} ``` -------------------------------- ### Example Usage of Callback Type Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Demonstrates how to define and use a callback function when making a bridge call. The callback receives response data from the handler. ```swift let callback: WKWebViewJavascriptBridgeBase.Callback = { response in if let dict = response as? [String: Any] { print("Response:", dict) } } bridge.call(handlerName: "fetchData", callback: callback) ``` -------------------------------- ### Example Message (Native to JavaScript) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Illustrates the structure of a message sent from native iOS code to JavaScript, including handler name, data, and an optional callback ID. ```swift let message: WKWebViewJavascriptBridgeBase.Message = [ "handlerName": "processData", "data": ["input": "value"], "callbackID": "native_iOS_cb_1" ] ``` -------------------------------- ### Example Usage of WKWebViewJavascriptBridgeBase Callback Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/api-reference/wkwebviewjavascriptbridgebase.md Demonstrates how to define and use a callback function that conforms to the WKWebViewJavascriptBridgeBase.Callback type alias. This is used to handle responses from JavaScript. ```swift let callback: WKWebViewJavascriptBridgeBase.Callback = { response in print("Received: \(response ?? \"nil\")") } ``` -------------------------------- ### Example Message (JavaScript to Native - Handler Call) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Demonstrates a message originating from JavaScript that invokes a native handler. It includes the handler name, data payload, and a callback ID for potential future responses. ```swift let callFromJS: WKWebViewJavascriptBridgeBase.Message = [ "handlerName": "getUserData", "data": ["userId": 123], "callbackID": "cb_1_1234567890" ] ``` -------------------------------- ### Required WKUserContentController Setup Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Configure the WKUserContentController for the bridge. The bridge automatically registers necessary message handlers and uses LeakAvoider. ```swift let config = WKWebViewConfiguration() let controller = config.userContentController // Message handlers are automatically registered by the bridge // No manual setup needed let webView = WKWebView(frame: .zero, configuration: config) ``` -------------------------------- ### Example Usage of Handler Type Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Illustrates how to define and register a handler to process messages from JavaScript. The handler can optionally send a response back using the provided callback. ```swift let handler: WKWebViewJavascriptBridgeBase.Handler = { params, callback in if let message = params?["message"] as? String { print("Message from JS:", message) } callback?(["status": "ok"]) } bridge.register(handlerName: "logMessage", handler: handler) ``` -------------------------------- ### Register Asynchronous JavaScript Handler Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Example of registering a handler that performs an asynchronous operation (like a fetch request) and then calls the response callback. ```javascript bridge.registerHandler('fetchUserProfile', function(data, responseCallback) { const userId = data.userId; fetch(`/api/users/${userId}`) .then(r => r.json()) .then(profile => { responseCallback(profile); }) .catch(err => { responseCallback({ error: err.message }); }); }); ``` -------------------------------- ### Complete WKWebView Javascript Bridge Initialization and Usage Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md This example demonstrates how to initialize the WKWebView Javascript Bridge and register handlers for native calls, as well as how to call native handlers from JavaScript. Ensure the `iOS_Native_InjectJavascript` message handler is configured on the native side. ```javascript function setupWKWebViewJavascriptBridge(callback) { if (window.WKWebViewJavascriptBridge) { return callback(WKWebViewJavascriptBridge); } if (window.WKWVJBCallbacks) { return window.WKWVJBCallbacks.push(callback); } window.WKWVJBCallbacks = [callback]; window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null) } setupWKWebViewJavascriptBridge(function(bridge) { // Register handlers that native can call bridge.registerHandler('displayAlert', function(data, responseCallback) { alert(data.message); responseCallback({ dismissed: true }); }); // Call a native handler bridge.callHandler('getDeviceInfo', null, function(deviceInfo) { console.log('Device:', deviceInfo.model, deviceInfo.osVersion); }); }); ``` -------------------------------- ### Example JavaScript Object for Serialization Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/message-protocol.md An example of a JavaScript object structure that can be serialized into a JSON string for communication with native code. ```javascript const message = { "handlerName": "test", "data": { "key": "value" }, "callbackID": "cb_1_1704067200000" }; // Produces: {"handlerName":"test","data":{"key":"value"},"callbackID":"cb_1_1704067200000"} ``` -------------------------------- ### Example: Call Native Handler to Trigger UI Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Demonstrates calling a native handler that performs an action on the native side, such as triggering a UI element, without sending data or expecting a response. ```javascript // Call with no arguments bridge.callHandler('triggerNativeUI'); ``` -------------------------------- ### Setup WKWebView Javascript Bridge in HTML Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md This script configures the WKWebViewJavascriptBridge by checking for its existence, managing callbacks, and injecting the bridge into the web view. It's used to establish communication between the web view and the native application. ```html ``` -------------------------------- ### Use WKWebViewJavascriptBridge in JavaScript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/README.md After setup, use the bridge in JavaScript to register handlers that the native side can call and to call native handlers. Ensure setupWKWebViewJavascriptBridge is called first. ```javascript setupWKWebViewJavascriptBridge(function(bridge) { /* Initialize your app here */ bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) { console.log('iOS called testJavascriptHandler with', data) responseCallback({ 'Javascript Says':'Right back atcha!' }) }) bridge.callHandler('testiOSCallback', {'foo': 'bar'}, function(response) { console.log('JS got response', response) }) }) ``` -------------------------------- ### Complete Round-Trip Message Flow (Native Initiates) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/architecture.md Visualizes a full communication cycle starting from native code, going to JavaScript, and returning a response. This covers the timing and sequence of events. ```text Time Native JavaScript ────────────────────────────────────────────────── 0 bridge.call(h, d, cb) │ 1 │ JS ready? │ ├─ startupQueue = nil │ └─ dispatch immediately │ 2 │─ Inject JS ─────────────┐ │ │ 3 │ ┌────▼──────────────┐ │ │ JS Bridge Loaded │ │ └────┬──────────────┘ │ │ 4 │ ┌────▼──────────────┐ │◄────── Flush All │ Dispatch Queued │ │ Startup Queue │ Messages │ │ └────────────────────┘ │ 5 ├─ evaluate: _handleMessageFromiOS(json) │ │ │ ┌────▼──────────────┐ │ │ JS Handler Called │ │ │ Gets data + cb │ │ └────┬──────────────┘ │ │ 6 │ cb(responseData) │ │ 7 │ Queue response msg │ │ 8 │ postMessage: FlushQueue │◄────────────────────────┤ │ 9 ├─ fetch queue via JS │ _fetchQueue() │ returns JSON array │◄────────────────────────┤ │ 10 ├─ flush(jsonString) ├─ deserialize → [message] ├─ find callback by responseID │ 11 └─ cb(responseData) Handler receives response ``` -------------------------------- ### Example Usage of WKWebViewJavascriptBridgeBase Handler Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/api-reference/wkwebviewjavascriptbridgebase.md Illustrates how to define and use a handler function that conforms to the WKWebViewJavascriptBridgeBase.Handler type alias. This handler processes incoming messages from JavaScript and can send a response back. ```swift let handler: WKWebViewJavascriptBridgeBase.Handler = { params, callback in print("Handler called with: \(params ?? [:])") callback?("Response data") } ``` -------------------------------- ### Native Handling Asynchronous Tasks with Callbacks Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Example of a native handler performing an asynchronous task and invoking the callback upon completion. This prevents callback leaks. ```swift // GOOD: Always clean up if not called bridge.register(handlerName: "asyncTask") { params, callback in DispatchQueue.main.asyncAfter(deadline: .now() + 5) { callback?(["result": "done"]) } } ``` -------------------------------- ### Install WKWebViewJavascriptBridge via Swift Package Manager Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/README.md Use Swift Package Manager in Xcode to add the WKWebViewJavascriptBridge library to your project. Ensure you add it to your target after adding the package dependency. ```swift // In Xcode: File > Add Package Dependencies // Enter: https://github.com/Lision/WKWebViewJavascriptBridge.git // Add to your target import WKWebViewJavascriptBridge ``` -------------------------------- ### Defensive Coding for Handler Parameters Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md This Swift example shows how to safely handle parameters received by a bridge handler. It includes checks for the existence of parameters and type casting for specific values like 'userId' to prevent runtime errors. ```swift bridge.register(handlerName: "handleData") { params, callback in guard let params = params else { callback?([" error": "No parameters"]) return } guard let userId = params["userId"] as? Int else { callback?(["error": "Invalid userId"]) return } // Now safe to use userId print("User ID: \(userId)") callback?(["status": "ok"]) } ``` -------------------------------- ### Example Valid Data Structure Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md This Swift dictionary demonstrates a valid data structure that can be safely transmitted through the bridge, including strings, integers, booleans, arrays, and nested dictionaries. ```swift let data: [String: Any] = [ "name": "John", "age": 30, "active": true, "scores": [85, 90, 95], "metadata": ["key": "value"] ] ``` -------------------------------- ### Initialize WKWebView and Bridge with Configuration Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md This snippet demonstrates the best practice for initializing a `WKWebView` and `WKWebViewJavascriptBridge` within a `UIViewController`. It includes creating a custom `WKWebViewConfiguration`, enabling development logging in debug builds, registering app-specific handlers, and loading web content. ```swift class MyViewController: UIViewController { let webView = WKWebView(frame: .zero, configuration: createWebViewConfig()) var bridge: WKWebViewJavascriptBridge! static func createWebViewConfig() -> WKWebViewConfiguration { let config = WKWebViewConfiguration() config.defaultWebpagePreferences.allowsContentJavaScript = true config.preferences.javaScriptCanOpenWindowsAutomatically = false return config } override func viewDidLoad() { super.viewDidLoad() view.addSubview(webView) // Initialize bridge bridge = WKWebViewJavascriptBridge(webView: webView) // Development logging #if DEBUG bridge.isLogEnable = true #endif // Register app handlers registerAppHandlers() // Load content loadWebContent() } private func registerAppHandlers() { bridge.register(handlerName: "app.getUserData") { params, callback in guard let userId = params?["id"] as? Int else { callback?(["error": "Missing id"]) return } // Fetch user data fetchUser(id: userId) { user in callback?(user) } } } private func loadWebContent() { if let url = URL(string: "https://example.com") { webView.load(URLRequest(url: url)) } } } ``` -------------------------------- ### Queue Messages Before JavaScript is Ready Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/architecture.md Implement the Startup Queue pattern to defer sending messages until the JavaScript environment is ready. Messages are appended to a queue if the bridge is not yet active. ```swift private func queue(message: Message) { if startupMessageQueue == nil { dispatch(message: message) } else { startupMessageQueue?.append(message) } } ``` -------------------------------- ### Instantiate WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/README.md Initialize the WKWebViewJavascriptBridge with a WKWebView instance. This is the first step in setting up the bridge. ```swift bridge = WKWebViewJavascriptBridge(webView: webView) ``` -------------------------------- ### JavaScript: Expected Console Log Messages Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/errors.md These messages indicate the bridge is operating correctly during setup, handler registration, and successful response handling. ```javascript // On successful setup console.log('Bridge ready') // On handler registration console.log('Handler registered: handlerName') // On successful call console.log('JS got response', response) ``` -------------------------------- ### Batch Operations vs. Multiple Calls Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md Demonstrates the difference between making multiple individual calls and a single batch call for adding users. Prefer batch operations for efficiency. ```swift // AVOID: Multiple calls for user in users { bridge.call(handlerName: "addUser", data: user) } ``` ```swift // PREFER: Single call with batch bridge.call(handlerName: "addUsers", data: ["users": users]) ``` -------------------------------- ### Initialize WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/INDEX.md Initialize the bridge with a WKWebView instance. This is the primary entry point for native integration. ```swift init(webView: WKWebView) ``` -------------------------------- ### setupWKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Initializes the JavaScript bridge. This function must be called before using other bridge functionalities. It ensures the bridge is ready and invokes a callback with the bridge object. ```APIDOC ## setupWKWebViewJavascriptBridge(callback: Function) ### Description Initializes the JavaScript bridge. This function must be called before using other bridge functionalities. It ensures the bridge is ready and invokes a callback with the bridge object. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **callback** (Function) - Required - Invoked with the bridge object when ready ### Request Example ```javascript setupWKWebViewJavascriptBridge(function(bridge) { console.log('Bridge ready!'); // Now you can use bridge.registerHandler, bridge.callHandler }); ``` ### Response #### Success Response (200) None (Callback is invoked with the bridge object) #### Response Example None ``` -------------------------------- ### Invoke or Remove Callbacks in Swift Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/README.md Always invoke or remove callbacks to prevent memory leaks, especially for asynchronous tasks. This example shows invoking a callback after a delay. ```swift bridge.register(handlerName: "asyncTask") { _, callback in DispatchQueue.main.asyncAfter(deadline: .now() + 5) { callback?(["done": true]) // Always call } } ``` -------------------------------- ### Example of Escaped JSON for JavaScript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/message-protocol.md Demonstrates the transformation of an original JSON string with a newline character into an escaped version suitable for embedding in JavaScript, ensuring correct parsing. ```plaintext - Original message: `{"text": "Hello\nWorld"}` - After escaping: `{"text": "Hello\\nWorld"}` - Embedded in JS: `WKWebViewJavascriptBridge._handleMessageFromiOS('{"text": "Hello\\nWorld"}')` - JavaScript parses correctly back to original ``` -------------------------------- ### Initialize JavaScript Bridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Call this function before using the bridge. It initializes the bridge and queues callbacks if it's not ready yet. ```javascript function setupWKWebViewJavascriptBridge(callback) { if (window.WKWebViewJavascriptBridge) { return callback(WKWebViewJavascriptBridge); } if (window.WKWVJBCallbacks) { return window.WKWVJBCallbacks.push(callback); } window.WKWVJBCallbacks = [callback]; window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null) } ``` -------------------------------- ### Default Bridge Initialization Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Initialize the bridge with default settings, which includes disabling logging for production environments. ```swift // Keep default settings let bridge = WKWebViewJavascriptBridge(webView: webView) // isLogEnable defaults to false ``` -------------------------------- ### Startup Message Queue Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/api-reference/wkwebviewjavascriptbridgebase.md Holds messages sent before JavaScript is ready. Outgoing messages are queued here and flushed once JavaScript injection completes. The queue is set to nil after injection. ```swift var startupMessageQueue: [Message]? = [] ``` -------------------------------- ### Recommended WKWebView Settings Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Enable JavaScript and disable file access for security. Other preferences like content mode can also be configured. ```swift let config = WKWebViewConfiguration() // Allow JavaScript config.defaultWebpagePreferences.allowsContentJavaScript = true // Disable file access by default (security) config.preferences.javaScriptCanOpenWindowsAutomatically = false // Optional: Configure other settings config.defaultWebpagePreferences.preferredContentMode = .desktop let webView = WKWebView(frame: .zero, configuration: config) ``` -------------------------------- ### Swift: Prevent Callback Leaks in Bridge Handlers Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/errors.md Ensure callbacks are always invoked or not registered to prevent memory leaks. This example shows a good practice of always calling the callback and a bad practice of conditional invocation. ```swift // GOOD: Always invoke callback or don't register one bridge.register(handlerName: "async") { params, callback in DispatchQueue.main.asyncAfter(deadline: .now() + 5) { callback?(["result": "done"]) } } // BAD: Conditional callback invocation bridge.register(handlerName: "bad") { params, callback in if someCondition { callback?(["result": "ok"]) } // Callback leaked if condition false } ``` -------------------------------- ### Mock Bridge for Testing Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md Implement a mock bridge conforming to a protocol for unit testing. This allows simulating bridge behavior without a real WKWebView. ```swift protocol BridgeProtocol { func call(handlerName: String, data: Any?, callback: ((Any?) -> Void)?) func register(handlerName: String, handler: @escaping (([String: Any]?, ((Any?) -> Void)?) -> Void)) } extension WKWebViewJavascriptBridge: BridgeProtocol {} class MockBridge: BridgeProtocol { var handlers: [String: (([String: Any]?, ((Any?) -> Void)?) -> Void)] = [: ] func call(handlerName: String, data: Any?, callback: ((Any?) -> Void)?) { // Mock implementation } func register(handlerName: String, handler: @escaping (([String: Any]?, ((Any?) -> Void)?) -> Void)) { handlers[handlerName] = handler } } ``` -------------------------------- ### Basic JavaScript Usage for WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/README.md This snippet shows how to integrate WKWebViewJavascriptBridge in JavaScript. It covers setting up the bridge, registering handlers for native calls, and calling native handlers. ```javascript function setupWKWebViewJavascriptBridge(callback) { if (window.WKWebViewJavascriptBridge) return callback(WKWebViewJavascriptBridge); if (window.WKWVJBCallbacks) return window.WKWVJBCallbacks.push(callback); window.WKWVJBCallbacks = [callback]; window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null) } setupWKWebViewJavascriptBridge(function(bridge) { // Register a handler that native can call bridge.registerHandler('jsHandler', function(data, callback) { console.log('Native called with:', data); callback({ result: 'done' }); }); // Call a native handler bridge.callHandler('myHandler', { key: 'value' }, function(response) { console.log('Native responded:', response); }); }); ``` -------------------------------- ### Swift: Prevent Handler Retain Cycles Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/errors.md Avoid retain cycles by using weak references within handler closures to ensure proper deallocation of self. This example demonstrates a good practice with a weak reference and a bad practice with a strong reference. ```swift // GOOD: Weak reference bridge.register(handlerName: "handler") { [weak self] params, callback in guard let self = self else { return } // Safe to use self } // BAD: Strong reference bridge.register(handlerName: "handler") { params, callback in self.property = "value" // Strong capture } ``` -------------------------------- ### Initialize WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/api-reference/wkwebviewjavascriptbridge.md Initialize the bridge with a WKWebView instance. This must be done after the WKWebView is created but before loading web content. The bridge automatically registers message handlers. ```swift public init(webView: WKWebView) ``` ```swift import UIKit import WebKit import WKWebViewJavascriptBridge class MyViewController: UIViewController { let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration()) var bridge: WKWebViewJavascriptBridge! override func viewDidLoad() { super.viewDidLoad() view.addSubview(webView) bridge = WKWebViewJavascriptBridge(webView: webView) webView.load(URLRequest(url: URL(string: "https://example.com")!)) } } ``` -------------------------------- ### Project File Organization Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/INDEX.md Overview of the directory structure for the WKWebView JavaScript Bridge project. This helps in navigating and understanding the location of different modules and documentation files. ```text output/ ├── README.md (Start here!) ├── INDEX.md (This file) ├── api-reference/ │ ├── wkwebviewjavascriptbridge.md (Main API) │ └── wkwebviewjavascriptbridgebase.md (Internal API) ├── javascript-bridge.md (JS API) ├── types.md (Type definitions) ├── configuration.md (Setup options) ├── usage-patterns.md (Code examples) ├── errors.md (Troubleshooting) ├── architecture.md (Internal design) └── message-protocol.md (Protocol spec) ``` -------------------------------- ### Basic Native Swift Usage for WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/README.md This snippet demonstrates how to set up WKWebViewJavascriptBridge in native Swift. It includes registering a handler for JavaScript calls and making calls to JavaScript handlers. ```swift let webView = WKWebView(frame: view.bounds) view.addSubview(webView) let bridge = WKWebViewJavascriptBridge(webView: webView) // Register a handler that JavaScript can call bridge.register(handlerName: "myHandler") { params, callback in print("JS called with: \(params)") callback?(["response": "success"]) } // Call a JavaScript handler bridge.call(handlerName: "jsHandler", data: ["key": "value"]) { response in print("JS responded: \(response)") } webView.load(URLRequest(url: URL(string: "https://example.com")!)) ``` -------------------------------- ### WKWebViewJavascriptBridge Component Architecture Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/architecture.md Illustrates the high-level structure of WKWebViewJavascriptBridge, showing the interaction between the native application, the bridge's public and internal APIs, WKScriptMessageHandler integration, and the JavaScript runtime within the WKWebView. ```text ┌─────────────────────────────────────────────────────┐ │ Your Native Application (Swift) │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ WKWebViewJavascriptBridge (Public API) │ │ │ │ - init(webView:) │ │ │ │ - register(handlerName:handler:) │ │ │ │ - call(handlerName:data:callback:) │ │ │ │ - remove(handlerName:) │ │ │ │ - reset() │ │ │ │ - isLogEnable │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ WKWebViewJavascriptBridgeBase (Internal) │ │ │ │ - Message serialization/deserialization │ │ │ │ - Handler dispatch │ │ │ │ - Callback tracking │ │ │ │ - Startup message queue │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ WKScriptMessageHandler Integration │ │ │ │ - iOS_Native_InjectJavascript │ │ │ │ - iOS_Native_FlushMessageQueue │ │ │ └────────────────────────────────────────────────┘ │ └────────────┬──────────────────────────────────────────┘ │ │ WKWebView Integration │ ┌────────────▼──────────────────────────────────────────┐ │ WebView JavaScript Runtime │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ WKWebViewJavascriptBridge (Injected JavaScript) │ │ │ │ - window.WKWebViewJavascriptBridge │ │ │ │ - registerHandler() │ │ │ │ - callHandler() │ │ │ │ - Message queue management │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ Your JavaScript Code │ │ │ │ - Handler functions │ │ │ │ - Bridge communication logic │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Native to JavaScript Message Flow Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/architecture.md Illustrates the steps involved when native code initiates a message to JavaScript. This includes the bridge construction, message queuing, and JavaScript execution. ```text 1. Native Code ├─ bridge.call(handlerName: "foo", data: {...}, callback: {...}) │ 2. WKWebViewJavascriptBridge ├─ Delegates to WKWebViewJavascriptBridgeBase.send() │ 3. WKWebViewJavascriptBridgeBase ├─ Constructs Message: ["handlerName": "foo", "data": {...}, "callbackID": "native_iOS_cb_1"] ├─ Calls queue(message:) │ 4. Queue Decision ├─ If JavaScript ready: │ └─ Calls dispatch(message:) │ ├─ Serializes message to JSON │ ├─ Escapes special characters │ └─ Evaluates JavaScript: WKWebViewJavascriptBridge._handleMessageFromiOS(json) │ └─ If JavaScript not ready: └─ Appends to startupMessageQueue (queued until JS ready) 5. JavaScript ├─ _handleMessageFromiOS() receives JSON ├─ Parses and dispatches to registered handler ├─ Handler executes with data and responseCallback └─ If callback provided, responseCallback queues response back to native 6. Response Flow (Return Path) ├─ JavaScript calls responseCallback(responseData) ├─ Creates message: ["handlerName": "foo", "responseID": "native_iOS_cb_1", "responseData": {...}] ├─ JavaScript queues this message └─ Next flush sends to native ``` -------------------------------- ### WKWebViewJavascriptBridge Initializer Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/api-reference/wkwebviewjavascriptbridge.md Initializes the WKWebViewJavascriptBridge with a WKWebView instance. This sets up the necessary handlers for bidirectional message passing between native code and JavaScript. ```APIDOC ## `init(webView: WKWebView)` ### Description Initializes the bridge with a WKWebView instance and sets up internal message handlers. ### Parameters #### Path Parameters - **webView** (WKWebView) - Required - The WKWebView instance to bridge communications with. Must not be nil. ### Returns Initialized WKWebViewJavascriptBridge instance ### Notes - Must be initialized after WKWebView is created but before loading web content - Automatically registers message handlers with the webView's userContentController - The bridge maintains a weak reference to the webView ### Usage Example ```swift import UIKit import WebKit import WKWebViewJavascriptBridge class MyViewController: UIViewController { let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration()) var bridge: WKWebViewJavascriptBridge! override func viewDidLoad() { super.viewDidLoad() view.addSubview(webView) bridge = WKWebViewJavascriptBridge(webView: webView) webView.load(URLRequest(url: URL(string: "https://example.com")!)) } } ``` ``` -------------------------------- ### Check if Bridge is Ready (JavaScript) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Checks for the existence of the main bridge object on the window, indicating that the bridge is ready for use. ```javascript if (window.WKWebViewJavascriptBridge) { // Bridge is ready } ``` -------------------------------- ### Response Dispatch Flow Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/message-protocol.md Explains how responses are dispatched back to the originating callback. This covers creating response messages, queuing them, and invoking the final callback. ```text callback(responseData) ↓ Create response message: { "responseID": id, "responseData": data } ↓ queue(message) ↓ If ready: dispatch immediately If not ready: add to startupMessageQueue ↓ Find original callback by ID ↓ Invoke callback with responseData ↓ Remove from pending callbacks ``` -------------------------------- ### Safe Initialization with Weak WebView Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md Initializes the bridge safely by holding a weak reference to the WKWebView. This prevents retain cycles. Ensure handlers are set up after bridge initialization. ```swift class BridgeManager: NSObject { weak var webView: WKWebView? var bridge: WKWebViewJavascriptBridge? func initializeBridge(with webView: WKWebView) { self.webView = webView bridge = WKWebViewJavascriptBridge(webView: webView) setupHandlers() } private func setupHandlers() { guard let bridge = bridge else { return } // Register handlers } } ``` -------------------------------- ### Send Array of Objects to JavaScript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md Demonstrates sending an array of dictionaries, where each dictionary represents an object with properties, to a JavaScript handler. ```swift let items = [ ["id": 1, "name": "Item 1", "selected": true], ["id": 2, "name": "Item 2", "selected": false], ["id": 3, "name": "Item 3", "selected": true] ] bridge.call(handlerName: "setItems", data: ["items": items]) ``` -------------------------------- ### Native Sending Response to JavaScript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Demonstrates how a native handler can send a JSON-serializable response back to JavaScript using the provided callback function. ```swift bridge.register(handlerName: "processData") { params, callback in // Callback is optional if let cb = callback { cb(["status": "success", "data": [1, 2, 3]]) } } ``` -------------------------------- ### WKWebViewJavascriptBridge Class Methods Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/MANIFEST.md This section details the public methods available on the WKWebViewJavascriptBridge class, including initialization, handler registration and calling, and bridge resetting. ```APIDOC ## init(webView:) ### Description Initializes the WKWebViewJavascriptBridge with a given WKWebView. ### Method - init ### Parameters #### Path Parameters - **webView** (WKWebView) - Required - The WKWebView instance to bridge with. ### Notes This method is essential for establishing the communication channel between Objective-C/Swift and JavaScript. ### Examples ```swift let bridge = WKWebViewJavascriptBridge.init(webView: myWebView) ``` ## register(handlerName:handler:) ### Description Registers a handler to be called from JavaScript. ### Method - register ### Parameters #### Path Parameters - **handlerName** (String) - Required - The name of the handler to register. - **handler** (Handler) - Required - The callback function to execute when the handler is invoked. ### Notes Handlers allow JavaScript to execute native code. ### Examples ```swift bridge.register(handlerName: "showAlert") { (data, callback) in // Handle alert } ``` ## call(handlerName:data:callback:) ### Description Calls a registered handler from JavaScript, optionally passing data and receiving a callback. ### Method - call ### Parameters #### Path Parameters - **handlerName** (String) - Required - The name of the handler to call. - **data** (Any) - Optional - Data to send to the handler. - **callback** (Callback) - Optional - A callback function to receive results from the handler. ### Notes This method is used to invoke native functionality from the web view. ### Examples ```swift bridge.call(handlerName: "fetchData", data: nil) { response in print(response) } ``` ## remove(handlerName:) ### Description Removes a previously registered handler. ### Method - remove ### Parameters #### Path Parameters - **handlerName** (String) - Required - The name of the handler to remove. ### Notes Use this to clean up handlers when they are no longer needed. ### Examples ```swift bridge.remove(handlerName: "oldHandler") ``` ## reset() ### Description Resets the bridge, removing all registered handlers and clearing the message queue. ### Method - reset ### Notes Useful for re-initializing the bridge or cleaning up state. ### Examples ```swift bridge.reset() ``` ``` -------------------------------- ### Enable Bridge Logging (Native) Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/errors.md Enable logging on the native side to help diagnose issues with message passing. ```swift bridge.isLogEnable = true ``` -------------------------------- ### Native Request and JavaScript Handler Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/message-protocol.md Native initiates a request with handler name, data, and a callback ID. JavaScript receives this, registers a handler, processes the data, and prepares a response. ```json { "handlerName": "calculateSum", "data": { "a": 5, "b": 3 }, "callbackID": "native_iOS_cb_1" } ``` ```javascript bridge.registerHandler('calculateSum', function(data, callback) { var result = data.a + data.b; // 8 callback({ sum: result }); }); ``` -------------------------------- ### JavaScript API: window.WKWebViewJavascriptBridge Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/INDEX.md APIs available in JavaScript for interacting with the native bridge. ```APIDOC ## JavaScript API: window.WKWebViewJavascriptBridge ### Description APIs available in JavaScript for interacting with the native bridge. ### Initialization ```javascript setupWKWebViewJavascriptBridge(callback) ``` #### Description Sets up the JavaScript side of the bridge. The callback is invoked once the bridge is ready. ### Methods #### `bridge.registerHandler(name, handler)` ##### Description Registers a JavaScript handler that can be called from native code. ##### Parameters - **name** (String) - The name of the handler. - **handler** (Function) - The JavaScript function to execute when the handler is called. ``` ```APIDOC #### `bridge.callHandler(name, [data], [callback])` ##### Description Calls a native handler from JavaScript. ##### Parameters - **name** (String) - The name of the native handler to call. - **data** (Any, optional) - Optional data to send to the native handler. - **callback** (Function, optional) - Optional callback function to receive a response from the native handler. ``` -------------------------------- ### Logging Wrapper for Bridge Calls Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/usage-patterns.md Create a logging wrapper for bridge calls to automatically log outgoing calls, data, and incoming responses. This simplifies debugging. ```swift extension WKWebViewJavascriptBridge { func callWithLogging(handlerName: String, data: Any? = nil, callback: WKWebViewJavascriptBridgeBase.Callback? = nil) { print("[Bridge] Calling: \(handlerName)") if let data = data { print("[Bridge] Data: \(data)") } call(handlerName: handlerName, data: data) { response in print("[Bridge] Response for \(handlerName): \(response ?? "nil")") callback?(response) } } } ``` -------------------------------- ### WKWebViewJavascriptBridge Methods Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/INDEX.md Provides methods for registering and calling handlers, and managing the bridge. ```APIDOC ## WKWebViewJavascriptBridge Methods ### Description Provides methods for registering and calling handlers, and managing the bridge. ### Methods #### `register(handlerName:handler:)` ##### Description Register a native handler to be called from JavaScript. ##### Parameters - **handlerName** (String) - The name of the handler to register. - **handler** (Handler) - The callback function to execute when the handler is invoked. ``` ```APIDOC #### `call(handlerName:data:callback:)` ##### Description Call a JavaScript handler registered in the web view. ##### Parameters - **handlerName** (String) - The name of the JavaScript handler to call. - **data** (Any?) - Optional data payload to send to the JavaScript handler. - **callback** (Callback?) - Optional callback function to receive a response from the JavaScript handler. ``` ```APIDOC #### `remove(handlerName:)` ##### Description Unregister a previously registered native handler. ##### Parameters - **handlerName** (String) - The name of the handler to remove. ``` ```APIDOC #### `reset()` ##### Description Clears all registered handlers and pending callbacks, resetting the bridge to its initial state. ``` -------------------------------- ### Default Implementation for Evaluate Javascript Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/types.md Provides a default implementation for `evaluateJavascript` that calls the main method with a nil completion handler. This allows for simpler calls when results are not needed. ```swift extension WKWebViewJavascriptBridgeBaseDelegate { func evaluateJavascript(javascript: String) { evaluateJavascript(javascript: javascript, completion: nil) } } ``` -------------------------------- ### Call Native Handler with Callback, No Data Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/javascript-bridge.md Call a native handler and provide a callback function, but send no data. ```javascript bridge.callHandler('handlerName', function(response) { }) ``` -------------------------------- ### Queue Messages Before JavaScript is Ready Source: https://github.com/lision/wkwebviewjavascriptbridge/blob/master/_autodocs/configuration.md Messages sent via `bridge.call` before the JavaScript environment is fully loaded are automatically queued. These messages are then flushed in order once the JavaScript is ready, ensuring no calls are lost. The startup message queue is cleared after flushing. ```swift // Messages sent before JS ready are queued bridge.call(handlerName: "handler1", data: data1) bridge.call(handlerName: "handler2", data: data2) // When JS loads, all queued messages are flushed // Messages are processed in order ```