Skip to content

Commit 4ab41bb

Browse files
committed
Remove the error parameter from all response callbacks. This change breaks API backwards compatibility!
Previously, responses were sent using either `response.respondWith(data)` or `response.respondWithError(error)`. Response handlers were then required to take two parameters: ` function responseHandler(error, responseData) { if (error) { /* handle error */ } ... } ` However, this approach causes confusion, as seen in GH issue marcuswestin#18. Instead, we do away with the notion of errors in responses and simply have response callback blocks with a single data parameter: `responseCallback(data)` and `function responseHandler(responseData) { ... }` To migrate from old ObjC code, simple replace all instances of `WVJBResponse* response` with `WVJBResponseCallback responseCallback`, and replace all instances of `response.respondWith(data)` with `responseCallback(data)`. To migrate from old Javascript code, replace all instances of `response.respondWith(data)` with `response(data)`.
1 parent 318e72a commit 4ab41bb

File tree

6 files changed

+83
-106
lines changed

6 files changed

+83
-106
lines changed

ExampleApp/ExampleApp.html

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<h1>WebViewJavascriptBridge Demo</h1>
1111
<script>
1212
window.onerror = function(err) {
13-
alert('window.onerror: ' + err)
13+
log('window.onerror: ' + err)
1414
}
1515
document.addEventListener('WebViewJavascriptBridgeReady', onBridgeReady, false)
1616
function onBridgeReady(event) {
@@ -20,24 +20,33 @@ <h1>WebViewJavascriptBridge Demo</h1>
2020
var log = document.getElementById('log')
2121
var el = document.createElement('div')
2222
el.className = 'logLine'
23-
el.innerHTML = uniqueId++ + '. ' + message + (data ? ': ' + JSON.stringify(data) : '')
23+
el.innerHTML = uniqueId++ + '. ' + message + (data ? ':<br/>' + JSON.stringify(data) : '')
2424
if (log.children.length) { log.insertBefore(el, log.children[0]) }
2525
else { log.appendChild(el) }
2626
}
27-
bridge.init(function(message) {
27+
bridge.init(function(message, responseCallback) {
2828
log('JS got a message', message)
29+
var data = { 'Javascript Responds':'Wee!' }
30+
log('JS responding with', data)
31+
responseCallback(data)
2932
})
3033

31-
bridge.registerHandler('testJavascriptHandler', function(data, response) {
32-
log('JS handler testJavascriptHandler was called', data)
33-
response.respondWith({ 'Javascript Says':'Right back atcha!' })
34+
bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
35+
log('ObjC called testJavascriptHandler with', data)
36+
var responseData = { 'Javascript Says':'Right back atcha!' }
37+
log('JS responding with', responseData)
38+
responseCallback(responseData)
3439
})
3540

3641
var button = document.getElementById('buttons').appendChild(document.createElement('button'))
3742
button.innerHTML = 'Send message to ObjC'
3843
button.ontouchstart = function(e) {
3944
e.preventDefault()
40-
bridge.send('Hello from JS button')
45+
var data = 'Hello from JS button'
46+
log('JS sending message', data)
47+
bridge.send(data, function(responseData) {
48+
log('JS got response', responseData)
49+
})
4150
}
4251

4352
document.body.appendChild(document.createElement('br'))
@@ -46,9 +55,9 @@ <h1>WebViewJavascriptBridge Demo</h1>
4655
callbackButton.innerHTML = 'Fire testObjcCallback'
4756
callbackButton.ontouchstart = function(e) {
4857
e.preventDefault()
49-
log("Calling handler testObjcCallback")
58+
log('JS calling handler "testObjcCallback"')
5059
bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {
51-
log('Got response from testObjcCallback', response)
60+
log('JS got response', response)
5261
})
5362
}
5463
}

ExampleApp/ExampleAppDelegate.m

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,18 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
1212

1313
[WebViewJavascriptBridge enableLogging];
1414

15-
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponse *response) {
15+
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
1616
NSLog(@"ObjC received message from JS: %@", data);
17-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ObjC got message from Javascript:" message:data delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
18-
[alert show];
17+
responseCallback(@"Response for message from ObjC");
1918
}];
2019

21-
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponse *response) {
20+
[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
2221
NSLog(@"testObjcCallback called: %@", data);
23-
[response respondWith:@"Response from testObjcCallback"];
22+
responseCallback(@"Response from testObjcCallback");
2423
}];
2524

26-
[_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id error, id responseData) {
27-
if (error) { return NSLog(@"Uh oh - I got an error: %@", error); }
28-
NSLog(@"objc got response! %@ %@", error, responseData);
25+
[_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) {
26+
NSLog(@"objc got response! %@", responseData);
2927
}];
3028

3129
[_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]];
@@ -54,12 +52,15 @@ - (void)renderButtons:(UIWebView*)webView {
5452
}
5553

5654
- (void)sendMessage:(id)sender {
57-
[_bridge send:@"A string sent from ObjC to JS"];
55+
[_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) {
56+
NSLog(@"sendMessage got response: %@", response);
57+
}];
5858
}
5959

6060
- (void)callHandler:(id)sender {
61-
[_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"] responseCallback:^(id error, id response) {
62-
NSLog(@"testJavascriptHandler responded: %@ %@", error, response);
61+
NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"];
62+
[_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) {
63+
NSLog(@"testJavascriptHandler responded: %@", response);
6364
}];
6465
}
6566

README.md

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,32 @@ To use a WebViewJavascriptBridge in your own project:
3636
3) Instantiate a UIWebView and a WebViewJavascriptBridge:
3737

3838
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds];
39-
WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponse* response) {
39+
WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
4040
NSLog(@"Received message from javascript: %@", data);
41-
[response respondWith:@"Right back atcha"];
42-
// or [response respondWithError:]
41+
responseCallback(@"Right back atcha");
4342
}];
4443

4544
4) Go ahead and send some messages from ObjC to javascript:
4645

4746
[bridge send:@"Well hello there"];
4847
[bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]];
49-
[bridge send:@"Give me a response, will you?" responseCallback:^(id error, id responseData) {
50-
NSLog(@"objc got its response! %@ %@", error, responseData);
48+
[bridge send:@"Give me a response, will you?" responseCallback:^(id responseData) {
49+
NSLog(@"ObjC got its response! %@ %@", responseData);
5150
}];
5251

5352
4) Finally, set up the javascript side:
5453

5554
document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) {
5655
var bridge = event.bridge
57-
bridge.init(function(message, response) {
56+
bridge.init(function(message, responseCallback) {
5857
alert('Received message: ' + message)
59-
if (response) {
60-
response.respondWith("Right back atcha")
61-
// or use response.respondWithError("Booh!")
58+
if (responseCallback) {
59+
responseCallback("Right back atcha")
6260
}
6361
})
6462
bridge.send('Hello from the javascript')
65-
bridge.send('Please respond to this', function responseCallback(error, responseData) {
66-
console.log("javascript got its response", error, responseData)
63+
bridge.send('Please respond to this', function responseCallback(responseData) {
64+
console.log("Javascript got its response", responseData)
6765
})
6866
}, false)
6967

@@ -77,20 +75,20 @@ API Reference
7775

7876
Create a javascript bridge for the given UIWebView.
7977

80-
The `WVJBResponse` will not be `nil` if the javascript expects a response.
78+
The `WVJBResponseCallback` will not be `nil` if the javascript expects a response.
8179

8280
Optionally, pass in `webViewDelegate:(UIWebViewDelegate*)webViewDelegate` if you need to respond to the [UIWebView's lifecycle events](http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html).
8381

8482
Example:
8583

86-
[WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponse response) {
84+
[WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
8785
NSLog(@"Received message from javascript: %@", data);
88-
if (response) {
89-
[response respondWith:@"Right back atcha"];
86+
if (responseCallback) {
87+
responseCallback(@"Right back atcha");
9088
}
9189
}]
9290

93-
[WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponse response) { /* ... */ }];
91+
[WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { /* ... */ }];
9492

9593
##### `[bridge send:(id)data]`
9694
##### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]`
@@ -101,8 +99,7 @@ Example:
10199

102100
[bridge send:@"Hi"];
103101
[bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]];
104-
[bridge send:@"I expect a response!" responseCallback:^(id error, id responseData) {
105-
if (error) { return NSLog(@"Uh oh, I got an error: %@", error); }
102+
[bridge send:@"I expect a response!" responseCallback:^(id responseData) {
106103
NSLog(@"Got response! %@", responseData);
107104
}];
108105

@@ -112,8 +109,8 @@ Register a handler called `handlerName`. The javascript can then call this handl
112109

113110
Example:
114111

115-
[bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponse response) {
116-
[response respondWith:[NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]];
112+
[bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) {
113+
responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]);
117114
}];
118115

119116
##### `[bridge callHandler:(NSString*)handlerName data:(id)data]`
@@ -124,8 +121,7 @@ Call the javascript handler called `handlerName`. Optionally expect a response b
124121
Example:
125122

126123
[bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"];
127-
[bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id error, id responseData) {
128-
if (error) { return NSLog(@"Huston, we got a problem: %@", error); }
124+
[bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) {
129125
NSLog(@"Current UIWebView page URL is: %@", responseData);
130126
}];
131127

@@ -153,37 +149,35 @@ The `response` object will be defined if if ObjC sent the message with a `WVJBRe
153149

154150
Example:
155151

156-
bridge.init(function(data, response) {
152+
bridge.init(function(data, responseCallback) {
157153
alert("Got data " + JSON.stringify(data))
158-
if (response) {
159-
response.respondWith("Right back atcha!")
160-
// or, response.respondWithError("It went wrong!")
154+
if (responseCallback) {
155+
responseCallback("Right back atcha!")
161156
}
162157
})
163158

164159
##### `bridge.send("Hi there!")`
165160
##### `bridge.send({ Foo:"Bar" })`
166-
##### `bridge.send(data, function responseCallback(error, responseData) { ... })`
161+
##### `bridge.send(data, function responseCallback(responseData) { ... })`
167162

168163
Send a message to ObjC. Optionally expect a response by giving a `responseCallback` function.
169164

170165
Example:
171166

172167
bridge.send("Hi there!")
173-
bridge.send("Hi there!", function(error, responseData) {
174-
if (error) { return alert("Uh oh, we got an error: "+error) }
175-
alert("I got a response! "+JSON.stringify(data))
168+
bridge.send("Hi there!", function(responseData) {
169+
alert("I got a response! "+JSON.stringify(responseData))
176170
})
177171

178-
##### `bridge.registerHandler("handlerName", function(error, responseData) { ... })`
172+
##### `bridge.registerHandler("handlerName", function(responseData) { ... })`
179173

180-
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 error, id responseData) { ... }]`
174+
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) { ... }]`
181175

182176
Example:
183177

184178
bridge.registerHandler("showAlert", function(data) { alert(data) })
185-
bridge.registerHandler("getCurrentPageUrl", function(data, response) {
186-
response.respondWith(document.location.toString())
179+
bridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) {
180+
responseCallback(document.location.toString())
187181
})
188182

189183

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#import <UIKit/UIKit.h>
22

3-
@class WVJBResponse;
4-
typedef void (^WVJBResponseCallback)(id error, id responseData);
5-
typedef void (^WVJBHandler)(id data, WVJBResponse* response);
3+
typedef void (^WVJBResponseCallback)(id responseData);
4+
typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback);
65

76
@interface WebViewJavascriptBridge : NSObject <UIWebViewDelegate>
87
+ (id)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler;
@@ -16,9 +15,3 @@ typedef void (^WVJBHandler)(id data, WVJBResponse* response);
1615
- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
1716
- (void)reset;
1817
@end
19-
20-
@interface WVJBResponse : NSObject
21-
- (WVJBResponse*) initWithCallbackId:(NSString*)callbackId bridge:(WebViewJavascriptBridge*)bridge;
22-
- (void) respondWith:(id)responseData;
23-
- (void) respondWithError:(id)error;
24-
@end

WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,14 @@
6363

6464
if (message.responseId) {
6565
var responseCallback = responseCallbacks[message.responseId]
66-
responseCallback(message.error, message.responseData)
66+
responseCallback(message.responseData)
6767
delete responseCallbacks[message.responseId]
6868
} else {
69-
var response
69+
var responseCallback
7070
if (message.callbackId) {
7171
var callbackResponseId = message.callbackId
72-
response = {
73-
respondWith: function(responseData) {
74-
_doSend({ responseId:callbackResponseId, responseData:responseData })
75-
},
76-
respondWithError: function(error) {
77-
_doSend({ responseId:callbackResponseId, error:error })
78-
}
72+
responseCallback = function(responseData) {
73+
_doSend({ responseId:callbackResponseId, responseData:responseData })
7974
}
8075
}
8176

@@ -85,9 +80,11 @@
8580
}
8681

8782
try {
88-
handler(message.data, response)
83+
handler(message.data, responseCallback)
8984
} catch(exception) {
90-
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
85+
if (typeof console != 'undefined') {
86+
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
87+
}
9188
}
9289
}
9390
})

0 commit comments

Comments
 (0)