An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.
If you like WebViewJavascriptBridge you may also want to check out WebViewProxy.
WebViewJavascriptBridge is used by a range of companies and projects. This list is incomplete, but feel free to add your's and send a PR.
- Facebook Messenger
- Facebook Paper
- Yardsale
- EverTrue
- Game Insight
- Altralogica
- Sush.io
- Flutterby Labs
- JD Media's 鼎盛中华
- Dojo4's Imbed
- CareZone
- Hemlig
Start with the Example Apps/ folder. Open either the iOS or OSX project and hit run to see it in action.
To use a WebViewJavascriptBridge in your own project:
- Drag the
WebViewJavascriptBridge
folder into your project.
- In the dialog that appears, uncheck "Copy items into destination group's folder" and select "Create groups for any folders"
-
Import the header file and declare an ivar property:
#import "WebViewJavascriptBridge.h"
...
@property WebViewJavascriptBridge* bridge;
-
Instantiate WebViewJavascriptBridge with a UIWebView (iOS) or WebView (OSX):
self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"Received message from javascript: %@", data); responseCallback(@"Right back atcha"); }];
-
Go ahead and send some messages from ObjC to javascript:
[self.bridge send:@"Well hello there"]; [self.bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]]; [self.bridge send:@"Give me a response, will you?" responseCallback:^(id responseData) { NSLog(@"ObjC got its response! %@", responseData); }];
-
Finally, set up the javascript side:
function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener('WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false) } }
connectWebViewJavascriptBridge(function(bridge) {
/* Init your app here */ bridge.init(function(message, responseCallback) { alert('Received message: ' + message) if (responseCallback) { responseCallback("Right back atcha") } }) bridge.send('Hello from the javascript') bridge.send('Please respond to this', function responseCallback(responseData) { console.log("Javascript got its response", responseData) })
})
Contributors: https://github.com/marcuswestin/WebViewJavascriptBridge/graphs/contributors
Forks: https://github.com/marcuswestin/WebViewJavascriptBridge/network/members
[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]
Create a javascript bridge for the given web view.
The WVJBResponseCallback
will not be nil
if the javascript expects a response.
Optionally, pass in webViewDelegate:(UIWebViewDelegate*)webViewDelegate
if you need to respond to the web view's lifecycle events.
Example:
[WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"Received message from javascript: %@", data);
if (responseCallback) {
responseCallback(@"Right back atcha");
}
}]
[WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { /* ... */ }];
Send a message to javascript. Optionally expect a response by giving a responseCallback
block.
Example:
[self.bridge send:@"Hi"];
[self.bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]];
[self.bridge send:@"I expect a response!" responseCallback:^(id responseData) {
NSLog(@"Got response! %@", responseData);
}];
Register a handler called handlerName
. The javascript can then call this handler with WebViewJavascriptBridge.callHandler("handlerName")
.
Example:
[self.bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) {
responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]);
}];
[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)callback]
Call the javascript handler called handlerName
. Optionally expect a response by giving a responseCallback
block.
Example:
[self.bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"];
[self.bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) {
NSLog(@"Current UIWebView page URL is: %@", responseData);
}];
WebViewJavascriptBridge
requires WebViewJavascriptBridge.js.txt
file that is injected into web view to create a bridge on JS side. Standard implementation uses mainBundle
to search for this file. If you e.g. build a static library and you have that file placed somewhere else you can use this method to specify which bundle should be searched for WebViewJavascriptBridge.js.txt
file:
[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webView webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle
Example:
[WebViewJavascriptBridge bridgeForWebView:_webView
webViewDelegate:self
handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"Received message from javascript: %@", data);
}
resourceBundle:[NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"ResourcesBundle" withExtension:@"bundle"]]
];
document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) { ... }, false)
Always wait for the WebViewJavascriptBridgeReady
DOM event.
Example:
document.addEventListener('WebViewJavascriptBridgeReady', function(event) {
var bridge = event.bridge
// Start using the bridge
}, false)
Initialize the bridge. This should be called inside of the 'WebViewJavascriptBridgeReady'
event handler.
The messageHandler
function will receive all messages sent from ObjC via [bridge send:(id)data]
and [bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]
.
The response
object will be defined if if ObjC sent the message with a WVJBResponseCallback
block.
Example:
bridge.init(function(data, responseCallback) {
alert("Got data " + JSON.stringify(data))
if (responseCallback) {
responseCallback("Right back atcha!")
}
})
Send a message to ObjC. Optionally expect a response by giving a responseCallback
function.
Example:
bridge.send("Hi there!")
bridge.send("Hi there!", function(responseData) {
alert("I got a response! "+JSON.stringify(responseData))
})
Register a handler called handlerName
. The ObjC can then call this handler with [bridge callHandler:"handlerName" data:@"Foo"]
and [bridge callHandler:"handlerName" data:@"Foo" responseCallback:^(id responseData) { ... }]
Example:
bridge.registerHandler("showAlert", function(data) { alert(data) })
bridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) {
responseCallback(document.location.toString())
})
Note: iOS4 support has not yet been tested in v2+.
WebViewJavascriptBridge uses NSJSONSerialization
by default. If you need iOS 4 support then you can use JSONKit, and add USE_JSONKIT
to the preprocessor macros for your project.