From 9d0513b0979285f4d51edec4cf6d4184f9db23a0 Mon Sep 17 00:00:00 2001 From: gotomanners Date: Tue, 28 Aug 2012 15:34:33 +0100 Subject: [PATCH 001/342] Fixed typo issue with sendMessage button function being replaced by callbackButton function --- WebViewJavascriptBridge/ExampleAppDelegate.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/ExampleAppDelegate.m b/WebViewJavascriptBridge/ExampleAppDelegate.m index 5be5e529..5eadc141 100644 --- a/WebViewJavascriptBridge/ExampleAppDelegate.m +++ b/WebViewJavascriptBridge/ExampleAppDelegate.m @@ -94,7 +94,7 @@ - (void)loadExamplePage { "" " var callbackButton = document.body.appendChild(document.createElement('button'));" " callbackButton.innerHTML = 'Click me to call ObjC callback';" - " callbackButton.onclick = button.ontouchstart = function() { WebViewJavascriptBridge.callObjcCallback('testObjcCallback', {'foo': 'bar'}); };" + " callbackButton.onclick = callbackButton.ontouchstart = function() { WebViewJavascriptBridge.callObjcCallback('testObjcCallback', {'foo': 'bar'}); };" " }" " " "" baseURL:nil]; From c4479a5e693c70ad321f55c5b410a6d08f5e3871 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 12 Sep 2012 18:25:55 -0700 Subject: [PATCH 002/342] Always send messages as objects (rather than strings); Make message handler a block rather than a delegate; Implement request/response pattern; --- .../project.pbxproj | 4 + WebViewJavascriptBridge/ExampleApp.html | 44 ++++ WebViewJavascriptBridge/ExampleAppDelegate.h | 3 +- WebViewJavascriptBridge/ExampleAppDelegate.m | 107 +++----- .../WebViewJavascriptBridge.h | 32 +-- .../WebViewJavascriptBridge.js | 133 +++++----- .../WebViewJavascriptBridge.m | 235 +++++++++--------- 7 files changed, 289 insertions(+), 269 deletions(-) create mode 100644 WebViewJavascriptBridge/ExampleApp.html diff --git a/WebViewJavascriptBridge.xcodeproj/project.pbxproj b/WebViewJavascriptBridge.xcodeproj/project.pbxproj index 26467d67..9d6d0804 100644 --- a/WebViewJavascriptBridge.xcodeproj/project.pbxproj +++ b/WebViewJavascriptBridge.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 2C66C03E14C787BA0050C940 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C66C03D14C787BA0050C940 /* WebViewJavascriptBridge.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 2C6D2131143017AF0069FA34 /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */; }; 2C8D041515E699AA0016052D /* WebViewJavascriptBridge.js in Resources */ = {isa = PBXBuildFile; fileRef = 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */; }; + 2CEB3E7D160155CF00548120 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CEB3E7C160155CF00548120 /* ExampleApp.html */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -29,6 +30,7 @@ 2C6D212F143017AF0069FA34 /* ExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; }; 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = WebViewJavascriptBridge.js; sourceTree = ""; }; + 2CEB3E7C160155CF00548120 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -78,6 +80,7 @@ 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */, 2C6D212F143017AF0069FA34 /* ExampleAppDelegate.h */, 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */, + 2CEB3E7C160155CF00548120 /* ExampleApp.html */, 2C1E9EA514099B4600C5C30E /* Supporting Files */, ); path = WebViewJavascriptBridge; @@ -147,6 +150,7 @@ files = ( 2C1E9EA914099B4600C5C30E /* InfoPlist.strings in Resources */, 2C8D041515E699AA0016052D /* WebViewJavascriptBridge.js in Resources */, + 2CEB3E7D160155CF00548120 /* ExampleApp.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebViewJavascriptBridge/ExampleApp.html b/WebViewJavascriptBridge/ExampleApp.html new file mode 100644 index 00000000..7bbbde8b --- /dev/null +++ b/WebViewJavascriptBridge/ExampleApp.html @@ -0,0 +1,44 @@ + + + + +

Javascript Bridge Demo

+ +
+ diff --git a/WebViewJavascriptBridge/ExampleAppDelegate.h b/WebViewJavascriptBridge/ExampleAppDelegate.h index 64112b92..1354ba43 100644 --- a/WebViewJavascriptBridge/ExampleAppDelegate.h +++ b/WebViewJavascriptBridge/ExampleAppDelegate.h @@ -1,12 +1,13 @@ #import #import "WebViewJavascriptBridge.h" -@interface ExampleAppDelegate : UIResponder +@interface ExampleAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UIWebView *webView; @property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge; +- (void)renderButtons; - (void)loadExamplePage; @end diff --git a/WebViewJavascriptBridge/ExampleAppDelegate.m b/WebViewJavascriptBridge/ExampleAppDelegate.m index 5eadc141..4fc62452 100644 --- a/WebViewJavascriptBridge/ExampleAppDelegate.m +++ b/WebViewJavascriptBridge/ExampleAppDelegate.m @@ -12,92 +12,59 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( self.webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; [self.window addSubview:self.webView]; - self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeWithDelegate:self]; - self.webView.delegate = self.javascriptBridge; - - UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; - [messageButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:messageButton aboveSubview:self.webView]; - messageButton.frame = CGRectMake(20, 400, 130, 45); + self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:self.webView handler:^(id data, WVJBCallback callback) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message from Javascript" message:data delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alert show]; + }]; - UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [callbackButton setTitle:@"Call callback" forState:UIControlStateNormal]; - [callbackButton addTarget:self action:@selector(callbackPressed:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:callbackButton aboveSubview:self.webView]; - callbackButton.frame = CGRectMake(170, 400, 130, 45); + + [self renderButtons]; // register a callback - [self.javascriptBridge registerObjcCallback:@"testObjcCallback" withCallback:^(NSDictionary *params){ - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ObjC callback called" - message:[NSString stringWithFormat:@"Foo: %@", [params objectForKey:@"foo"]] - delegate:nil - cancelButtonTitle:@"OK" - otherButtonTitles:nil]; - [alert show]; + [self.javascriptBridge registerHandler:@"testObjcCallback" callback:^(id data, WVJBCallback callback) { + NSLog(@"testObjcCallback called: %@", data); + callback(@"Response from testObjcCallback"); }]; - - [self.javascriptBridge sendMessage:@"Message from ObjC before Webview is complete!" toWebView:self.webView]; - [self.javascriptBridge callJavascriptCallback:@"testJsCallback" - withParams:[NSDictionary dictionaryWithObjectsAndKeys:@"before ready", @"foo", nil] - toWebView:self.webView]; - - [self loadExamplePage]; - - [self.javascriptBridge sendMessage:@"Message 2 from ObjC before Webview is complete!" toWebView:self.webView]; + [self.javascriptBridge send:@"A string sent from ObjC before Webview has loaded."]; + [self.javascriptBridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; + + [self loadExamplePage]; + + [self.javascriptBridge send:@"A string sent from ObjC after Webview has loaded."]; + [self.window makeKeyAndVisible]; return YES; } -- (void)buttonPressed:(id)sender { - [self.javascriptBridge sendMessage:@"Message from ObjC on normal situations!" toWebView:self.webView]; +- (void)renderButtons { + UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; + [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; + [self.window insertSubview:messageButton aboveSubview:self.webView]; + messageButton.frame = CGRectMake(20, 400, 130, 45); + + UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; + [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; + [self.window insertSubview:callbackButton aboveSubview:self.webView]; + callbackButton.frame = CGRectMake(170, 400, 130, 45); } -- (void)callbackPressed:(id)sender { - [self.javascriptBridge callJavascriptCallback:@"testJsCallback" - withParams:[NSDictionary dictionaryWithObjectsAndKeys:@"bar", @"foo", nil] - toWebView:self.webView]; +- (void)sendMessage:(id)sender { + [self.javascriptBridge send:@"A string sent from ObjC to JS"]; } -- (void)javascriptBridge:(WebViewJavascriptBridge *)bridge receivedMessage:(NSString *)message fromWebView:(UIWebView *)webView { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message from Javascript" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alert show]; +- (void)callHandler:(id)sender { + [self.javascriptBridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"] responseCallback:^(id data) { + NSLog(@"testJavascriptHandler responded: %@", data); + }]; } - (void)loadExamplePage { - [self.webView loadHTMLString:@"" - "" - "" - " " - "" - "

Javascript Bridge Demo

" - " " - "" baseURL:nil]; + NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; + NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; + [self.webView loadHTMLString:appHtml baseURL:nil]; } @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 90ec20df..66270330 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -1,33 +1,21 @@ #import -@class WebViewJavascriptBridge; - -@protocol WebViewJavascriptBridgeDelegate - -- (void)javascriptBridge:(WebViewJavascriptBridge *)bridge receivedMessage:(NSString *)message fromWebView:(UIWebView *)webView; +typedef void (^WVJBCallback)(id data); +typedef void (^WVJBHandler)(id data, WVJBCallback callback); -@end +@class WebViewJavascriptBridge; @interface WebViewJavascriptBridge : NSObject -@property (nonatomic, assign) IBOutlet id delegate; - -/* Create a javascript bridge with the given delegate for handling messages */ -+ (id)javascriptBridgeWithDelegate:(id )delegate; - -/* Send a message to the web view. Make sure that this javascript bridge is the delegate - * of the webview before calling this method (see ExampleAppDelegate.m) */ -- (void)sendMessage:(NSString *)message toWebView:(UIWebView *)webView; - -/* Reset startup messaging queue */ -- (void)resetQueue; - -- (void)callJavascriptCallback:(NSString *)name toWebView:(UIWebView *)webView; ++ (id)javascriptBridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; ++ (id)javascriptBridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler webViewDelegate:(id )webViewDelegate; -- (void)callJavascriptCallback:(NSString *)name withParams:(NSDictionary *)params toWebView:(UIWebView *)webView; +- (void)send:(id)message; +- (void)send:(id)message responseCallback:(WVJBCallback)responseCallback; -- (void)registerObjcCallback:(NSString *)name withCallback:(void (^)(NSDictionary *params))callback; +- (void)registerHandler:(NSString*)handlerName callback:(WVJBHandler)handler; -- (void)unregisterObjcCallback:(NSString *)name; +- (void)callHandler:(NSString*)handlerName data:(id)data; +- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBCallback)responseCallback; @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.js b/WebViewJavascriptBridge/WebViewJavascriptBridge.js index 9971c850..f518a3e0 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.js +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.js @@ -1,89 +1,104 @@ ;(function() { if (window.WebViewJavascriptBridge) { return } - var _readyMessageIframe, - _sendMessageQueue = [], - _receiveMessageQueue = [], - _jsCallbacks = [], - _MESSAGE_SEPERATOR = '%@', - _CUSTOM_PROTOCOL_SCHEME = '%@', - _QUEUE_HAS_MESSAGE = '%@', - _CALLBACK_MESSAGE_PREFIX = '%@', - _CALLBACK_FUNCTION_KEY = '%@', - _CALLBACK_ARGUMENTS_KEY = '%@' - + var messagingIframe + var sendMessageQueue = [] + var receiveMessageQueue = [] + var messageHandlers = {} + + var MESSAGE_SEPARATOR = '__WVJB_MESSAGE_SEPERATOR__' + var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme' + var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__' + + var responseCallbacks = {} + var uniqueId = 1 + function _createQueueReadyIframe(doc) { - _readyMessageIframe = doc.createElement('iframe') - _readyMessageIframe.style.display = 'none' - doc.documentElement.appendChild(_readyMessageIframe) + messagingIframe = doc.createElement('iframe') + messagingIframe.style.display = 'none' + doc.documentElement.appendChild(messagingIframe) } - function _sendMessage(message) { - _sendMessageQueue.push(message) - _readyMessageIframe.src = _CUSTOM_PROTOCOL_SCHEME + '://' + _QUEUE_HAS_MESSAGE + function init(messageHandler) { + if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') } + WebViewJavascriptBridge._messageHandler = messageHandler + var receivedMessages = receiveMessageQueue + receiveMessageQueue = null + for (var i=0; i webViewDelegate; +@property (nonatomic, copy) WVJBHandler messageHandler; -- (void)_flushMessageQueueFromWebView:(UIWebView *)webView; -- (void)_doSendMessage:(NSString*)message toWebView:(UIWebView *)webView; +- (void)_flushMessageQueue; +- (void)_queueData:(NSDictionary*)data responseCallback:(WVJBCallback)responseCallback handlerName:(NSString*)handlerName; +- (void)_dispatchMessage:(NSDictionary*)message; @end @implementation WebViewJavascriptBridge -@synthesize delegate = _delegate; -@synthesize startupMessageQueue = _startupMessageQueue; +static NSString *MESSAGE_SEPARATOR = @"__WVJB_MESSAGE_SEPERATOR__"; +static NSString *CUSTOM_PROTOCOL_SCHEME = @"wvjbscheme"; +static NSString *QUEUE_HAS_MESSAGE = @"__WVJB_QUEUE_MESSAGE__"; -static NSString *MESSAGE_SEPARATOR = @"__wvjb_sep__"; -static NSString *CUSTOM_PROTOCOL_SCHEME = @"webviewjavascriptbridge"; -static NSString *QUEUE_HAS_MESSAGE = @"queuehasmessage"; -static NSString *CALLBACK_MESSAGE_PREFIX = @"__wvjb_cb__"; -static NSString *CALLBACK_FUNCTION_KEY = @"wvjb_function"; -static NSString *CALLBACK_ARGUMENTS_KEY = @"wvjb_arguments"; - -+ (id)javascriptBridgeWithDelegate:(id )delegate { - WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; - bridge.delegate = delegate; - [bridge resetQueue]; - return bridge; ++ (id)javascriptBridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { + return [self javascriptBridgeForWebView:webView handler:handler webViewDelegate:nil]; } - -- (id)init { - if (self = [super init]) { - self.javascriptCallbacks = [NSMutableDictionary dictionary]; - } - return self; ++ (id)javascriptBridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)messageHandler webViewDelegate:(id)webViewDelegate { + WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + bridge.messageHandler = messageHandler; + bridge.startupMessageQueue = [NSMutableArray array]; + bridge.responseCallbacks = [NSMutableDictionary dictionary]; + bridge.messageHandlers = [NSMutableDictionary dictionary]; + bridge.uniqueId = 0; + bridge.webView = webView; + bridge.webViewDelegate = webViewDelegate; + webView.delegate = bridge; + return bridge; } -- (void)dealloc { - _delegate = nil; +- (void)send:(NSDictionary *)data { + [self send:data responseCallback:nil]; } -- (void)sendMessage:(NSString *)message toWebView:(UIWebView *)webView { - if (self.startupMessageQueue) { - [self.startupMessageQueue addObject:message]; - } else { - [self _doSendMessage:message toWebView: webView]; - } +- (void)send:(NSDictionary *)data responseCallback:(WVJBCallback)responseCallback { + [self _queueData:data responseCallback:responseCallback handlerName:nil]; } -- (void)resetQueue { - self.startupMessageQueue = [[NSMutableArray alloc] init]; +- (void)callHandler:(NSString *)handlerName data:(id)data { + [self callHandler:handlerName data:data responseCallback:nil]; } -- (void)callJavascriptCallback:(NSString *)name toWebView:(UIWebView *)webView { - [self callJavascriptCallback:name withParams:[NSDictionary dictionary] toWebView:webView]; +- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBCallback)responseCallback { + [self _queueData:data responseCallback:responseCallback handlerName:handlerName]; } -- (void)callJavascriptCallback:(NSString *)name withParams:(NSDictionary *)params toWebView:(UIWebView *)webView { - NSDictionary *callParams = [NSDictionary dictionaryWithObjectsAndKeys: - name, CALLBACK_FUNCTION_KEY, - params, CALLBACK_ARGUMENTS_KEY, - nil]; -#ifdef USE_JSONKIT - NSString *encodedParams = [callParams JSONString]; -#else - NSString *encodedParams = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:callParams options:0 error:nil] - encoding:NSUTF8StringEncoding]; -#endif - - [self sendMessage:[NSString stringWithFormat:@"%@%@", CALLBACK_MESSAGE_PREFIX, encodedParams] - toWebView:webView]; +- (void)registerHandler:(NSString *)handlerName callback:(WVJBHandler)handler { + [self.messageHandlers setObject:handler forKey:handlerName]; } -- (void)registerObjcCallback:(NSString *)name withCallback:(void (^)(NSDictionary *params))callback { - [self.javascriptCallbacks setObject:[callback copy] forKey:name]; -} +- (void)_queueData:(NSDictionary *)data responseCallback:(WVJBCallback)responseCallback handlerName:(NSString*)handlerName { + NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; + + if (responseCallback) { + NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%d", ++_uniqueId]; + [self.responseCallbacks setObject:responseCallback forKey:callbackId]; + [message setObject:callbackId forKey:@"callbackId"]; + } -- (void)unregisterObjcCallback:(NSString *)name { - [self.javascriptCallbacks removeObjectForKey:name]; + if (handlerName) { + [message setObject:handlerName forKey:@"handlerName"]; + } + + if (self.startupMessageQueue) { + [self.startupMessageQueue addObject:message]; + } else { + [self _dispatchMessage:message]; + } } -- (void)_doSendMessage:(NSString *)message toWebView:(UIWebView *)webView { - message = [message stringByReplacingOccurrencesOfString:@"\\n" withString:@"\\\\n"]; - message = [message stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]; - message = [message stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; - [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", message]]; +- (void)_dispatchMessage:(NSDictionary *)message { +#ifdef USE_JSONKIT + NSString *messageJSON = [message JSONString]; +#else + NSString *messageJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; +#endif + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\n" withString:@"\\\\n"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; } -- (void)_flushMessageQueueFromWebView:(UIWebView *)webView { - NSString *messageQueueString = [webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"]; +- (void)_flushMessageQueue { + NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"]; NSArray* messages = [messageQueueString componentsSeparatedByString:MESSAGE_SEPARATOR]; - for (NSString *message in messages) { - if ([message hasPrefix:CALLBACK_MESSAGE_PREFIX]) { - // should be a JSON encoded callback - NSString *payload = [message stringByReplacingOccurrencesOfString:CALLBACK_MESSAGE_PREFIX withString:@""]; + for (NSString *messageJSON in messages) { + // normal message - pass to bridge #ifdef USE_JSONKIT - NSDictionary *decodedMessage = [payload objectFromJSONString]; + NSDictionary *message = [payload objectFromJSONString]; #else - NSDictionary *decodedMessage = [NSJSONSerialization JSONObjectWithData:[payload dataUsingEncoding:NSUTF8StringEncoding] - options:0 - error:nil]; + NSDictionary *message = [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; #endif - NSString *callbackName = [decodedMessage objectForKey:CALLBACK_FUNCTION_KEY]; - - void (^callback)(NSDictionary *params) = [self.javascriptCallbacks objectForKey:callbackName]; - - if (callback == NULL) { - // don't have a callback - pass to bridge - [self.delegate javascriptBridge:self receivedMessage:message fromWebView:webView]; - } else { - // call the callback - callback([decodedMessage objectForKey:CALLBACK_ARGUMENTS_KEY]); - } + WVJBCallback responseCallback = NULL; + if ([message objectForKey:@"callbackId"]) { + __block NSString* responseId = [message objectForKey:@"callbackId"]; + responseCallback = ^(NSDictionary* data) { + NSDictionary* response = [NSDictionary dictionaryWithObjectsAndKeys: responseId, @"responseId", data, @"data", nil]; + [self send:response]; + }; + } + + WVJBHandler handler = self.messageHandler; + if ([message objectForKey:@"handlerName"]) { + handler = [self.messageHandlers objectForKey:[message objectForKey:@"handlerName"]]; + } else if ([message objectForKey:@"responseId"]) { + handler = [self.responseCallbacks objectForKey:[message objectForKey:@"responseId"]]; + } + + @try { + handler([message objectForKey:@"data"], responseCallback); } - else { - // normal message - pass to bridge - [self.delegate javascriptBridge:self receivedMessage:message fromWebView:webView]; + @catch (NSException *exception) { + NSLog(@"WebViewJavascriptBridge: WARNING: handler threw. %@ %@", message, exception); } } } @@ -128,58 +133,54 @@ - (void)_flushMessageQueueFromWebView:(UIWebView *)webView { #pragma mark UIWebViewDelegate - (void)webViewDidFinishLoad:(UIWebView *)webView { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge" ofType:@"js"]; - NSString *jsTemplate = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - NSString *js = [NSString stringWithFormat:jsTemplate, - MESSAGE_SEPARATOR, - CUSTOM_PROTOCOL_SCHEME, - QUEUE_HAS_MESSAGE, - CALLBACK_MESSAGE_PREFIX, - CALLBACK_FUNCTION_KEY, - CALLBACK_ARGUMENTS_KEY]; - - if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - [webView stringByEvaluatingJavaScriptFromString:js]; + if (webView != _webView) { return; } + + if (![[_webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge" ofType:@"js"]; + NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + [_webView stringByEvaluatingJavaScriptFromString:js]; } - for (id message in self.startupMessageQueue) { - [self _doSendMessage:message toWebView: webView]; + if (self.startupMessageQueue) { + for (id queuedMessage in self.startupMessageQueue) { + [self _dispatchMessage:queuedMessage]; + } + self.startupMessageQueue = nil; } - - self.startupMessageQueue = nil; - - if(self.delegate != nil && [self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { - [self.delegate webViewDidFinishLoad:webView]; + + if (self.webViewDelegate) { + [self.webViewDelegate webViewDidFinishLoad:webView]; } } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { - if(self.delegate != nil && [self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { - [self.delegate webView:webView didFailLoadWithError:error]; + if (webView != _webView) { return; } + if (self.webViewDelegate) { + [self.webViewDelegate webView:_webView didFailLoadWithError:error]; } } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + if (webView != _webView) { return YES; } NSURL *url = [request URL]; - if (![[url scheme] isEqualToString:CUSTOM_PROTOCOL_SCHEME]) { - if (self.delegate != nil && [self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { - return [self.delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; + if ([[url scheme] isEqualToString:CUSTOM_PROTOCOL_SCHEME]) { + if ([[url host] isEqualToString:QUEUE_HAS_MESSAGE]) { + [self _flushMessageQueue]; + } else { + NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", CUSTOM_PROTOCOL_SCHEME, [url path]); } - return YES; - } - - if ([[url host] isEqualToString:QUEUE_HAS_MESSAGE]) { - [self _flushMessageQueueFromWebView: webView]; + return NO; + } else if (self.webViewDelegate) { + return [self.webViewDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; } else { - NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", CUSTOM_PROTOCOL_SCHEME, [url path]); + return YES; } - - return NO; } - (void)webViewDidStartLoad:(UIWebView *)webView { - if(self.delegate != nil && [self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { - [self.delegate webViewDidStartLoad:webView]; + if (webView != _webView) { return; } + if (self.webViewDelegate) { + [self.webViewDelegate webViewDidStartLoad:webView]; } } From b56bd0b4c06bc2270c1e13e66ad9b1f4833d9341 Mon Sep 17 00:00:00 2001 From: Valerio Santinelli Date: Thu, 13 Sep 2012 12:08:18 +0200 Subject: [PATCH 003/342] Fixed some missing escaping of parameters when sent as JSON --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index e1bafd0f..8b349e1d 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -89,7 +89,9 @@ - (void)_dispatchMessage:(NSDictionary *)message { #else NSString *messageJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; #endif + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\\\\\\\"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\n" withString:@"\\\\n"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\r" withString:@"\\\\r"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; From 2c8789be9a660e191ef589d8b39cd9c8eff8ef98 Mon Sep 17 00:00:00 2001 From: Valerio Santinelli Date: Thu, 13 Sep 2012 12:23:05 +0200 Subject: [PATCH 004/342] Fixed a typo when using JSONKIT --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 8b349e1d..e9cdca2f 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -103,7 +103,7 @@ - (void)_flushMessageQueue { for (NSString *messageJSON in messages) { // normal message - pass to bridge #ifdef USE_JSONKIT - NSDictionary *message = [payload objectFromJSONString]; + NSDictionary *message = [messageJSON objectFromJSONString]; #else NSDictionary *message = [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; #endif From 6a76196aea4c5b364678578ca0c658b6f2ee93a8 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 10:37:09 -0700 Subject: [PATCH 005/342] escape according to http://stackoverflow.com/questions/5569794/escape-nsstring-for-javascript-input --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index e9cdca2f..f3d7b620 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -89,11 +89,12 @@ - (void)_dispatchMessage:(NSDictionary *)message { #else NSString *messageJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; #endif - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\\\\\\\"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\n" withString:@"\\\\n"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\r" withString:@"\\\\r"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; } From cc2bb082ce9a272407aea04c81fa1ade44f03801 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 10:38:14 -0700 Subject: [PATCH 006/342] Add @tanis2000 to contributors --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 625fefdc..4709a25f 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,5 @@ Contributors - [@psineur](https://github.com/psineur) Stepan Generalov - [@sergiocampama](https://github.com/sergiocampama) Sergio Campamá - [@stringbean](https://github.com/stringbean) Michael Stringer +- [@tanis2000](https://github.com/tanis2000) Valerio Santinelli + From 56e4be03f67708ff6c9c84baeb811a2731534582 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 11:19:58 -0700 Subject: [PATCH 007/342] Make it simpler to setup the bridge - just copy in a single directory as oppposed to three files --- ExampleApp.xcodeproj/project.pbxproj | 289 ++++++++++++++++++ .../ExampleApp-Info.plist | 13 +- .../ExampleApp-Prefix.pch | 2 +- .../ExampleApp.html | 0 .../ExampleAppDelegate.h | 5 +- .../ExampleAppDelegate.m | 31 +- .../en.lproj/InfoPlist.strings | 0 .../main.m | 8 + README.md | 43 ++- .../project.pbxproj | 277 ----------------- .../WebViewJavascriptBridge.h | 1 + ...idge.js => WebViewJavascriptBridge.js.txt} | 0 .../WebViewJavascriptBridge.m | 6 +- 13 files changed, 343 insertions(+), 332 deletions(-) create mode 100644 ExampleApp.xcodeproj/project.pbxproj rename WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist => ExampleApp/ExampleApp-Info.plist (73%) rename WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch => ExampleApp/ExampleApp-Prefix.pch (65%) rename {WebViewJavascriptBridge => ExampleApp}/ExampleApp.html (100%) rename {WebViewJavascriptBridge => ExampleApp}/ExampleAppDelegate.h (72%) rename {WebViewJavascriptBridge => ExampleApp}/ExampleAppDelegate.m (81%) rename {WebViewJavascriptBridge => ExampleApp}/en.lproj/InfoPlist.strings (100%) rename {WebViewJavascriptBridge => ExampleApp}/main.m (61%) delete mode 100644 WebViewJavascriptBridge.xcodeproj/project.pbxproj rename WebViewJavascriptBridge/{WebViewJavascriptBridge.js => WebViewJavascriptBridge.js.txt} (100%) diff --git a/ExampleApp.xcodeproj/project.pbxproj b/ExampleApp.xcodeproj/project.pbxproj new file mode 100644 index 00000000..678d6cd1 --- /dev/null +++ b/ExampleApp.xcodeproj/project.pbxproj @@ -0,0 +1,289 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; }; + 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC11602563600548120 /* Foundation.framework */; }; + 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC31602563600548120 /* CoreGraphics.framework */; }; + 2CEB3ECA1602563600548120 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CEB3EC81602563600548120 /* InfoPlist.strings */; }; + 2CEB3ECC1602563600548120 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEB3ECB1602563600548120 /* main.m */; }; + 2CEB3ED01602563600548120 /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEB3ECF1602563600548120 /* ExampleAppDelegate.m */; }; + 2CEB3F5216025A4E00548120 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CEB3F5016025A4E00548120 /* WebViewJavascriptBridge.js.txt */; }; + 2CEB3F5316025A4E00548120 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEB3F5116025A4E00548120 /* WebViewJavascriptBridge.m */; }; + 2CEB3F5516025A9000548120 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CEB3F5416025A9000548120 /* ExampleApp.html */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2CEB3EBB1602563600548120 /* ExampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 2CEB3EC11602563600548120 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 2CEB3EC31602563600548120 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 2CEB3EC71602563600548120 /* ExampleApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-Info.plist"; sourceTree = ""; }; + 2CEB3EC91602563600548120 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 2CEB3ECB1602563600548120 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 2CEB3ECD1602563600548120 /* ExampleApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-Prefix.pch"; sourceTree = ""; }; + 2CEB3ECE1602563600548120 /* ExampleAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; }; + 2CEB3ECF1602563600548120 /* ExampleAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; + 2CEB3F4F16025A4E00548120 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; + 2CEB3F5016025A4E00548120 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2CEB3F5116025A4E00548120 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; + 2CEB3F5416025A9000548120 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2CEB3EB81602563600548120 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */, + 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */, + 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2CEB3EB01602563600548120 = { + isa = PBXGroup; + children = ( + 2CEB3EC51602563600548120 /* ExampleApp */, + 2CEB3EBE1602563600548120 /* Frameworks */, + 2CEB3EBC1602563600548120 /* Products */, + ); + sourceTree = ""; + }; + 2CEB3EBC1602563600548120 /* Products */ = { + isa = PBXGroup; + children = ( + 2CEB3EBB1602563600548120 /* ExampleApp.app */, + ); + name = Products; + sourceTree = ""; + }; + 2CEB3EBE1602563600548120 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2CEB3EBF1602563600548120 /* UIKit.framework */, + 2CEB3EC11602563600548120 /* Foundation.framework */, + 2CEB3EC31602563600548120 /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2CEB3EC51602563600548120 /* ExampleApp */ = { + isa = PBXGroup; + children = ( + 2CEB3ECE1602563600548120 /* ExampleAppDelegate.h */, + 2CEB3ECF1602563600548120 /* ExampleAppDelegate.m */, + 2CEB3F5416025A9000548120 /* ExampleApp.html */, + 2CEB3F4E16025A4E00548120 /* WebViewJavascriptBridge */, + 2CEB3EC61602563600548120 /* Supporting Files */, + ); + path = ExampleApp; + sourceTree = ""; + }; + 2CEB3EC61602563600548120 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2CEB3EC71602563600548120 /* ExampleApp-Info.plist */, + 2CEB3EC81602563600548120 /* InfoPlist.strings */, + 2CEB3ECB1602563600548120 /* main.m */, + 2CEB3ECD1602563600548120 /* ExampleApp-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 2CEB3F4E16025A4E00548120 /* WebViewJavascriptBridge */ = { + isa = PBXGroup; + children = ( + 2CEB3F4F16025A4E00548120 /* WebViewJavascriptBridge.h */, + 2CEB3F5016025A4E00548120 /* WebViewJavascriptBridge.js.txt */, + 2CEB3F5116025A4E00548120 /* WebViewJavascriptBridge.m */, + ); + path = WebViewJavascriptBridge; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2CEB3EBA1602563600548120 /* ExampleApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp" */; + buildPhases = ( + 2CEB3EB71602563600548120 /* Sources */, + 2CEB3EB81602563600548120 /* Frameworks */, + 2CEB3EB91602563600548120 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ExampleApp; + productName = ExampleApp; + productReference = 2CEB3EBB1602563600548120 /* ExampleApp.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2CEB3EB21602563600548120 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0450; + ORGANIZATIONNAME = "Marcus Westin"; + }; + buildConfigurationList = 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2CEB3EB01602563600548120; + productRefGroup = 2CEB3EBC1602563600548120 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2CEB3EBA1602563600548120 /* ExampleApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2CEB3EB91602563600548120 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2CEB3ECA1602563600548120 /* InfoPlist.strings in Resources */, + 2CEB3F5216025A4E00548120 /* WebViewJavascriptBridge.js.txt in Resources */, + 2CEB3F5516025A9000548120 /* ExampleApp.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2CEB3EB71602563600548120 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2CEB3ECC1602563600548120 /* main.m in Sources */, + 2CEB3ED01602563600548120 /* ExampleAppDelegate.m in Sources */, + 2CEB3F5316025A4E00548120 /* WebViewJavascriptBridge.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2CEB3EC81602563600548120 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 2CEB3EC91602563600548120 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2CEB3ED11602563600548120 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 2CEB3ED21602563600548120 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2CEB3ED41602563600548120 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch"; + INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 2CEB3ED51602563600548120 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ExampleApp/ExampleApp-Prefix.pch"; + INFOPLIST_FILE = "ExampleApp/ExampleApp-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2CEB3ED11602563600548120 /* Debug */, + 2CEB3ED21602563600548120 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2CEB3ED41602563600548120 /* Debug */, + 2CEB3ED51602563600548120 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2CEB3EB21602563600548120 /* Project object */; +} diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist b/ExampleApp/ExampleApp-Info.plist similarity index 73% rename from WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist rename to ExampleApp/ExampleApp-Info.plist index 310fa6ea..2e36c495 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist +++ b/ExampleApp/ExampleApp-Info.plist @@ -8,10 +8,8 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleIconFiles - CFBundleIdentifier - com.marcuswestin.${PRODUCT_NAME:rfc1034identifier} + com.example.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -26,16 +24,13 @@ 1.0 LSRequiresIPhoneOS - UISupportedInterfaceOrientations + UIRequiredDeviceCapabilities - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight + armv7 - UISupportedInterfaceOrientations~ipad + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch b/ExampleApp/ExampleApp-Prefix.pch similarity index 65% rename from WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch rename to ExampleApp/ExampleApp-Prefix.pch index 4916c385..29f2d2ac 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch +++ b/ExampleApp/ExampleApp-Prefix.pch @@ -1,5 +1,5 @@ // -// Prefix header for all source files of the 'WebViewJavascriptBridge' target in the 'WebViewJavascriptBridge' project +// Prefix header for all source files of the 'ExampleApp' target in the 'ExampleApp' project // #import diff --git a/WebViewJavascriptBridge/ExampleApp.html b/ExampleApp/ExampleApp.html similarity index 100% rename from WebViewJavascriptBridge/ExampleApp.html rename to ExampleApp/ExampleApp.html diff --git a/WebViewJavascriptBridge/ExampleAppDelegate.h b/ExampleApp/ExampleAppDelegate.h similarity index 72% rename from WebViewJavascriptBridge/ExampleAppDelegate.h rename to ExampleApp/ExampleAppDelegate.h index 1354ba43..5fc2d78b 100644 --- a/WebViewJavascriptBridge/ExampleAppDelegate.h +++ b/ExampleApp/ExampleAppDelegate.h @@ -4,10 +4,9 @@ @interface ExampleAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; -@property (strong, nonatomic) UIWebView *webView; @property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge; -- (void)renderButtons; -- (void)loadExamplePage; +- (void)renderButtons:(UIWebView*)webView; +- (void)loadExamplePage:(UIWebView*)webView; @end diff --git a/WebViewJavascriptBridge/ExampleAppDelegate.m b/ExampleApp/ExampleAppDelegate.m similarity index 81% rename from WebViewJavascriptBridge/ExampleAppDelegate.m rename to ExampleApp/ExampleAppDelegate.m index 4fc62452..5ef8c202 100644 --- a/WebViewJavascriptBridge/ExampleAppDelegate.m +++ b/ExampleApp/ExampleAppDelegate.m @@ -3,51 +3,46 @@ @implementation ExampleAppDelegate @synthesize window = _window; -@synthesize webView = _webView; @synthesize javascriptBridge = _javascriptBridge; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - - self.webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; - [self.window addSubview:self.webView]; - - self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:self.webView handler:^(id data, WVJBCallback callback) { + UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; + [self.window addSubview:webView]; + + self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message from Javascript" message:data delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; }]; - - [self renderButtons]; - - // register a callback [self.javascriptBridge registerHandler:@"testObjcCallback" callback:^(id data, WVJBCallback callback) { NSLog(@"testObjcCallback called: %@", data); callback(@"Response from testObjcCallback"); }]; - + [self.javascriptBridge send:@"A string sent from ObjC before Webview has loaded."]; [self.javascriptBridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; - [self loadExamplePage]; - + [self renderButtons:webView]; + [self loadExamplePage:webView]; + [self.javascriptBridge send:@"A string sent from ObjC after Webview has loaded."]; [self.window makeKeyAndVisible]; return YES; } -- (void)renderButtons { +- (void)renderButtons:(UIWebView*)webView { UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:messageButton aboveSubview:self.webView]; + [self.window insertSubview:messageButton aboveSubview:webView]; messageButton.frame = CGRectMake(20, 400, 130, 45); UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:callbackButton aboveSubview:self.webView]; + [self.window insertSubview:callbackButton aboveSubview:webView]; callbackButton.frame = CGRectMake(170, 400, 130, 45); } @@ -61,10 +56,10 @@ - (void)callHandler:(id)sender { }]; } -- (void)loadExamplePage { +- (void)loadExamplePage:(UIWebView*)webView { NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; - [self.webView loadHTMLString:appHtml baseURL:nil]; + [webView loadHTMLString:appHtml baseURL:nil]; } @end diff --git a/WebViewJavascriptBridge/en.lproj/InfoPlist.strings b/ExampleApp/en.lproj/InfoPlist.strings similarity index 100% rename from WebViewJavascriptBridge/en.lproj/InfoPlist.strings rename to ExampleApp/en.lproj/InfoPlist.strings diff --git a/WebViewJavascriptBridge/main.m b/ExampleApp/main.m similarity index 61% rename from WebViewJavascriptBridge/main.m rename to ExampleApp/main.m index 5887dbf1..a724dc9c 100644 --- a/WebViewJavascriptBridge/main.m +++ b/ExampleApp/main.m @@ -1,3 +1,11 @@ +// +// main.m +// ExampleApp +// +// Created by Marcus Westin on 9/13/12. +// Copyright (c) 2012 Marcus Westin. All rights reserved. +// + #import #import "ExampleAppDelegate.h" diff --git a/README.md b/README.md index 4709a25f..92b45aac 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ WebViewJavascriptBridge ======================= -An iOS bridge for sending messages to and from javascript in a UIWebView +An iOS bridge for sending messages to and from javascript in a UIWebView. Getting started --------------- -Just open the Xcode project (requires Xcode > 4.2) and hit run to see the example application work. +Just open the Xcode project and hit run to see the example application. -Usage +Setup ----- See ExampleAppDelegate.* for example code. To use it in your own project: -1) Copy `WebViewJavascriptBridge/WebViewJavascriptBridge.h`, `WebViewJavascriptBridge/WebViewJavascriptBridge.m` and `WebViewJavascriptBridge/WebViewJavascriptBridge-template.js` into your Xcode project +1) Copy `WebViewJavascriptBridge` folder into your project. -2) Instantiate a UIWebView, a WebViewJavascriptBridge, and set yourself as the bridge's delegate +2) Instantiate a UIWebView and a WebViewJavascriptBridge: #import #import "WebViewJavascriptBridge.h" @@ -26,39 +26,36 @@ See ExampleAppDelegate.* for example code. To use it in your own project: @implementation ExampleAppDelegate - - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - { - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - - self.webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; - [self.window addSubview:self.webView]; - self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeWithDelegate:self]; - self.webView.delegate = self.javascriptBridge; - - [self.window makeKeyAndVisible]; - return YES; - } + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - - (void)javascriptBridge:(WebViewJavascriptBridge *)bridge receivedMessage:(NSString *)message fromWebView:(UIWebView *)webView - { - NSLog(@"MyJavascriptBridgeDelegate received message: %@", message); + UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; + WebViewJavascriptBridge* javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { + NSLog(@"Received message from javascript: %@", data); + }]; + + [self.window addSubview:self.webView]; + [self.window makeKeyAndVisible]; + return YES; } @end 3) Go ahead and send some messages from Objc to javascript - [self.javascriptBridge sendMessage:@"Well hello there" toWebView:self.webView]; + [javascriptBridge sendMessage:@"Well hello there" toWebView:self.webView]; 4) Finally, set up the javascript side of things document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady() { - WebViewJavascriptBridge.setMessageHandler(function(message) { + WebViewJavascriptBridge.init(function(message) { alert('Received message: ' + message) }) - WebViewJavascriptBridge.sendMessage('Hello from the javascript') + WebViewJavascriptBridge.send('Hello from the javascript') }, false) +5) Additional APIs: Responses + ### Registering callbacks The JS to ObjC and ObjC to JS callbacks use `NSJSONSerialization` to convert to/from JSON. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/) by adding `USE_JSONKIT` to the preprocessor macros for your project (you will need to include JSONKit in your project). diff --git a/WebViewJavascriptBridge.xcodeproj/project.pbxproj b/WebViewJavascriptBridge.xcodeproj/project.pbxproj deleted file mode 100644 index 9d6d0804..00000000 --- a/WebViewJavascriptBridge.xcodeproj/project.pbxproj +++ /dev/null @@ -1,277 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 2C1E9EA114099B4600C5C30E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1E9EA014099B4600C5C30E /* UIKit.framework */; }; - 2C1E9EA314099B4600C5C30E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1E9EA214099B4600C5C30E /* Foundation.framework */; }; - 2C1E9EA914099B4600C5C30E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2C1E9EA714099B4600C5C30E /* InfoPlist.strings */; }; - 2C1E9EAB14099B4600C5C30E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1E9EAA14099B4600C5C30E /* main.m */; }; - 2C66C03E14C787BA0050C940 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C66C03D14C787BA0050C940 /* WebViewJavascriptBridge.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 2C6D2131143017AF0069FA34 /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */; }; - 2C8D041515E699AA0016052D /* WebViewJavascriptBridge.js in Resources */ = {isa = PBXBuildFile; fileRef = 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */; }; - 2CEB3E7D160155CF00548120 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CEB3E7C160155CF00548120 /* ExampleApp.html */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 2C1E9E9C14099B4600C5C30E /* WebViewJavascriptBridge.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebViewJavascriptBridge.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 2C1E9EA014099B4600C5C30E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 2C1E9EA214099B4600C5C30E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 2C1E9EA614099B4600C5C30E /* WebViewJavascriptBridge-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WebViewJavascriptBridge-Info.plist"; sourceTree = ""; }; - 2C1E9EA814099B4600C5C30E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 2C1E9EAA14099B4600C5C30E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2C1E9EAC14099B4600C5C30E /* WebViewJavascriptBridge-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WebViewJavascriptBridge-Prefix.pch"; sourceTree = ""; }; - 2C66C03C14C787BA0050C940 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; - 2C66C03D14C787BA0050C940 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; - 2C6D212F143017AF0069FA34 /* ExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; }; - 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; - 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = WebViewJavascriptBridge.js; sourceTree = ""; }; - 2CEB3E7C160155CF00548120 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 2C1E9E9914099B4600C5C30E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2C1E9EA114099B4600C5C30E /* UIKit.framework in Frameworks */, - 2C1E9EA314099B4600C5C30E /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2C1E9E9114099B4600C5C30E = { - isa = PBXGroup; - children = ( - 2C1E9EA414099B4600C5C30E /* WebViewJavascriptBridge */, - 2C1E9E9F14099B4600C5C30E /* Frameworks */, - 2C1E9E9D14099B4600C5C30E /* Products */, - ); - sourceTree = ""; - }; - 2C1E9E9D14099B4600C5C30E /* Products */ = { - isa = PBXGroup; - children = ( - 2C1E9E9C14099B4600C5C30E /* WebViewJavascriptBridge.app */, - ); - name = Products; - sourceTree = ""; - }; - 2C1E9E9F14099B4600C5C30E /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2C1E9EA014099B4600C5C30E /* UIKit.framework */, - 2C1E9EA214099B4600C5C30E /* Foundation.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2C1E9EA414099B4600C5C30E /* WebViewJavascriptBridge */ = { - isa = PBXGroup; - children = ( - 2C66C03C14C787BA0050C940 /* WebViewJavascriptBridge.h */, - 2C66C03D14C787BA0050C940 /* WebViewJavascriptBridge.m */, - 2C8D041415E699AA0016052D /* WebViewJavascriptBridge.js */, - 2C6D212F143017AF0069FA34 /* ExampleAppDelegate.h */, - 2C6D2130143017AF0069FA34 /* ExampleAppDelegate.m */, - 2CEB3E7C160155CF00548120 /* ExampleApp.html */, - 2C1E9EA514099B4600C5C30E /* Supporting Files */, - ); - path = WebViewJavascriptBridge; - sourceTree = ""; - }; - 2C1E9EA514099B4600C5C30E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 2C1E9EA614099B4600C5C30E /* WebViewJavascriptBridge-Info.plist */, - 2C1E9EA714099B4600C5C30E /* InfoPlist.strings */, - 2C1E9EAA14099B4600C5C30E /* main.m */, - 2C1E9EAC14099B4600C5C30E /* WebViewJavascriptBridge-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 2C1E9E9B14099B4600C5C30E /* WebViewJavascriptBridge */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2C1E9EB214099B4600C5C30E /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridge" */; - buildPhases = ( - 2C1E9E9814099B4600C5C30E /* Sources */, - 2C1E9E9914099B4600C5C30E /* Frameworks */, - 2C1E9E9A14099B4600C5C30E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WebViewJavascriptBridge; - productName = WebViewJavascriptBridge; - productReference = 2C1E9E9C14099B4600C5C30E /* WebViewJavascriptBridge.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 2C1E9E9314099B4600C5C30E /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0420; - ORGANIZATIONNAME = Clover; - }; - buildConfigurationList = 2C1E9E9614099B4600C5C30E /* Build configuration list for PBXProject "WebViewJavascriptBridge" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 2C1E9E9114099B4600C5C30E; - productRefGroup = 2C1E9E9D14099B4600C5C30E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 2C1E9E9B14099B4600C5C30E /* WebViewJavascriptBridge */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 2C1E9E9A14099B4600C5C30E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2C1E9EA914099B4600C5C30E /* InfoPlist.strings in Resources */, - 2C8D041515E699AA0016052D /* WebViewJavascriptBridge.js in Resources */, - 2CEB3E7D160155CF00548120 /* ExampleApp.html in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 2C1E9E9814099B4600C5C30E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2C1E9EAB14099B4600C5C30E /* main.m in Sources */, - 2C6D2131143017AF0069FA34 /* ExampleAppDelegate.m in Sources */, - 2C66C03E14C787BA0050C940 /* WebViewJavascriptBridge.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 2C1E9EA714099B4600C5C30E /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 2C1E9EA814099B4600C5C30E /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 2C1E9EB014099B4600C5C30E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 2C1E9EB114099B4600C5C30E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 2C1E9EB314099B4600C5C30E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch"; - INFOPLIST_FILE = "WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 2C1E9EB414099B4600C5C30E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "WebViewJavascriptBridge/WebViewJavascriptBridge-Prefix.pch"; - INFOPLIST_FILE = "WebViewJavascriptBridge/WebViewJavascriptBridge-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2C1E9E9614099B4600C5C30E /* Build configuration list for PBXProject "WebViewJavascriptBridge" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2C1E9EB014099B4600C5C30E /* Debug */, - 2C1E9EB114099B4600C5C30E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2C1E9EB214099B4600C5C30E /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridge" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2C1E9EB314099B4600C5C30E /* Debug */, - 2C1E9EB414099B4600C5C30E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 2C1E9E9314099B4600C5C30E /* Project object */; -} diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 66270330..1b4073c1 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -15,6 +15,7 @@ typedef void (^WVJBHandler)(id data, WVJBCallback callback); - (void)registerHandler:(NSString*)handlerName callback:(WVJBHandler)handler; +- (void)callHandler:(NSString*)handlerName; - (void)callHandler:(NSString*)handlerName data:(id)data; - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBCallback)responseCallback; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.js b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge.js rename to WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index f3d7b620..99c2a697 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -51,6 +51,10 @@ - (void)send:(NSDictionary *)data responseCallback:(WVJBCallback)responseCallbac [self _queueData:data responseCallback:responseCallback handlerName:nil]; } +- (void)callHandler:(NSString *)handlerName { + [self callHandler:handlerName data:nil responseCallback:nil]; +} + - (void)callHandler:(NSString *)handlerName data:(id)data { [self callHandler:handlerName data:data responseCallback:nil]; } @@ -139,7 +143,7 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { if (webView != _webView) { return; } if (![[_webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge" ofType:@"js"]; + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [_webView stringByEvaluatingJavaScriptFromString:js]; } From 1f74d234c6785cc27cfef9dc4f109f44538f2eb7 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 11:53:20 -0700 Subject: [PATCH 008/342] clean up api and documentation --- ExampleApp/ExampleAppDelegate.m | 6 +- README.md | 135 +++++++++--------- .../WebViewJavascriptBridge.h | 10 +- .../WebViewJavascriptBridge.m | 12 +- 4 files changed, 82 insertions(+), 81 deletions(-) diff --git a/ExampleApp/ExampleAppDelegate.m b/ExampleApp/ExampleAppDelegate.m index 5ef8c202..d797dcc0 100644 --- a/ExampleApp/ExampleAppDelegate.m +++ b/ExampleApp/ExampleAppDelegate.m @@ -10,14 +10,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; [self.window addSubview:webView]; - self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { + self.javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message from Javascript" message:data delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; }]; - [self.javascriptBridge registerHandler:@"testObjcCallback" callback:^(id data, WVJBCallback callback) { + [self.javascriptBridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"testObjcCallback called: %@", data); - callback(@"Response from testObjcCallback"); + responseCallback(@"Response from testObjcCallback"); }]; [self.javascriptBridge send:@"A string sent from ObjC before Webview has loaded."]; diff --git a/README.md b/README.md index 92b45aac..49f2e2bf 100644 --- a/README.md +++ b/README.md @@ -8,98 +8,100 @@ Getting started Just open the Xcode project and hit run to see the example application. -Setup ------ +Setup your project +------------------ -See ExampleAppDelegate.* for example code. To use it in your own project: +See ExampleApp/* for example code. To use it in your own project: -1) Copy `WebViewJavascriptBridge` folder into your project. +1) Drag the `WebViewJavascriptBridge` folder into your project. -2) Instantiate a UIWebView and a WebViewJavascriptBridge: +In the dialog that appears: +- Uncheck "Copy items into destination group's folder (if needed)" +- Select "Create groups for any folders" - #import - #import "WebViewJavascriptBridge.h" +2) Import the header file: - @interface ExampleAppDelegate : UIResponder - - @end - - @implementation ExampleAppDelegate - - - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + #import "WebViewJavascriptBridge.h" - UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; - WebViewJavascriptBridge* javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { - NSLog(@"Received message from javascript: %@", data); - }]; - - [self.window addSubview:self.webView]; - [self.window makeKeyAndVisible]; - return YES; - } +3) Instantiate a UIWebView and a WebViewJavascriptBridge: - @end + UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; + WebViewJavascriptBridge* javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { + NSLog(@"Received message from javascript: %@", data); + }]; -3) Go ahead and send some messages from Objc to javascript +4) Go ahead and send some messages from Objc to javascript: - [javascriptBridge sendMessage:@"Well hello there" toWebView:self.webView]; + [javascriptBridge send:@"Well hello there"]; + [javascriptBridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]]; + [javascriptBridge send:@"Give me a response, will you?" responseCallback:^(id data) { + NSLog(@"I got a response! %@", data); + }]; -4) Finally, set up the javascript side of things +4) Finally, set up the javascript side of things: document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady() { - WebViewJavascriptBridge.init(function(message) { - alert('Received message: ' + message) + WebViewJavascriptBridge.init(function(message, responseCallback) { + alert('Received message: ' + message) + if (responseCallback) { + responseCallback("Right back atcha") + } }) WebViewJavascriptBridge.send('Hello from the javascript') }, false) -5) Additional APIs: Responses - -### Registering callbacks - -The JS to ObjC and ObjC to JS callbacks use `NSJSONSerialization` to convert to/from JSON. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/) by adding `USE_JSONKIT` to the preprocessor macros for your project (you will need to include JSONKit in your project). - -#### JS to ObjC - -You can register Objective-C blocks and call them from Javascript. In Objective-C register a block with the bridge: +5) Optional API: Registered handlers - [self.javascriptBridge registerObjcCallback:@"testObjcCallback" withCallback:^(NSDictionary *params){ - NSLog(@"ObjC callback [testObjcCallback] called with params: %@", params); - }]; +This lets you register named handlers for e.g. command handling. You should register handlers -Then call from Javascript using: +*Note:* You need to 1) register ObjC handlers before loading the UIWebView, and 2) register javascript handlers before calling `WebViewJavascriptBridge.init`. - WebViewJavascriptBridge.callObjcCallback('testObjcCallback', { 'foo': 'bar' }); - -This will result in the following being logged: - - ObjC callback [testObjcCallback] called with params: { 'foo' = 'bar'; } - -#### ObjC to JS - -You can also register Javascript functions and call them from Objective-C. In Javascript register a function with the bridge: +In ObjC: + + // Register handler + [javascriptBridge registerHandler:@"greetPerson" responseCallback:^(id data, WVJBCallback callback) { + callback([NSString stringWithFormat:@"Hello, %@", [data objectForKey:@"name"]]); + }]; + // Call javascript handlers + [javascriptBridge callHandler:@"showAlert" data:@"FooBar"]; + [javascriptBridge callHandler:@"getUrl" data:nil callback:^(id data) { + NSLog(@"UIWebView url is %@", data); + }]; + +In javascript: + + // Register handlers + WebViewJavascriptBridge.registerHandler('showAlert', function(data) { + alert(data) + }) + WebViewJavascriptBridge.registerHandler('getUrl', function(data, responseCallback) { + responseCallback(document.location.toString()) + }) + // Call ObjC handler + WebViewJavascriptBridge.callHandler('greetPerson', { name:'Marcus' }, function responseCallback(data) { + alert("ObjC created greeting: "+ data) + }) - WebViewJavascriptBridge.registerJsCallback('testJsCallback', function(params) { - var el = document.body.appendChild(document.createElement('div')); - el.innerHTML = 'JS [testJsCallback] called with params: ' + JSON.stringify(params); - }); +### iOS4 support (with JSONKit) -Then call from Objective-C using: + WebViewJavascriptBridge uses `NSJSONSerialization` by default. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. - [self.javascriptBridge callJavascriptCallback:@"testJsCallback" - withParams:[NSDictionary dictionaryWithObjectsAndKeys:@"bar", @"foo", nil] - toWebView:self.webView]; +### ObjC API Reference -This will result in a div with the following getting added to the HTML: +- `[WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*) handler:(WVJBHandler)]` - JS [testJsCallback] called with params: {"foo":"bar"} +Create a javascript bridge for the given webview. -*Note:* You should register any callbacks before you call `WebViewJavascriptBridge.setMessageHandler` otherwise any callback calls received before the HTML is fully loaded will be delivered as normal messages. +Example: + + [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback responseCallback) { + NSLog(@"Received message from javascript: %@", data); + if (responseCallback) { + responseCallback(@"Right back atcha") + } + }] -ARC ---- -If you're using ARC in your project, add `-fno-objc-arc` as a compiler flag to the `WebViewJavascriptBridge.m` file. +... More to come soon ... Contributors ------------ @@ -109,4 +111,3 @@ Contributors - [@sergiocampama](https://github.com/sergiocampama) Sergio Campamá - [@stringbean](https://github.com/stringbean) Michael Stringer - [@tanis2000](https://github.com/tanis2000) Valerio Santinelli - diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 1b4073c1..7ac1ac70 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -1,7 +1,7 @@ #import -typedef void (^WVJBCallback)(id data); -typedef void (^WVJBHandler)(id data, WVJBCallback callback); +typedef void (^WVJBResponseCallback)(id data); +typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @class WebViewJavascriptBridge; @@ -11,12 +11,12 @@ typedef void (^WVJBHandler)(id data, WVJBCallback callback); + (id)javascriptBridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler webViewDelegate:(id )webViewDelegate; - (void)send:(id)message; -- (void)send:(id)message responseCallback:(WVJBCallback)responseCallback; +- (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; -- (void)registerHandler:(NSString*)handlerName callback:(WVJBHandler)handler; +- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; - (void)callHandler:(NSString*)handlerName; - (void)callHandler:(NSString*)handlerName data:(id)data; -- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBCallback)responseCallback; +- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 99c2a697..301b876e 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -15,7 +15,7 @@ @interface WebViewJavascriptBridge () @property (nonatomic, copy) WVJBHandler messageHandler; - (void)_flushMessageQueue; -- (void)_queueData:(NSDictionary*)data responseCallback:(WVJBCallback)responseCallback handlerName:(NSString*)handlerName; +- (void)_queueData:(NSDictionary*)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; - (void)_dispatchMessage:(NSDictionary*)message; @end @@ -47,7 +47,7 @@ - (void)send:(NSDictionary *)data { [self send:data responseCallback:nil]; } -- (void)send:(NSDictionary *)data responseCallback:(WVJBCallback)responseCallback { +- (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback { [self _queueData:data responseCallback:responseCallback handlerName:nil]; } @@ -59,15 +59,15 @@ - (void)callHandler:(NSString *)handlerName data:(id)data { [self callHandler:handlerName data:data responseCallback:nil]; } -- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBCallback)responseCallback { +- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { [self _queueData:data responseCallback:responseCallback handlerName:handlerName]; } -- (void)registerHandler:(NSString *)handlerName callback:(WVJBHandler)handler { +- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { [self.messageHandlers setObject:handler forKey:handlerName]; } -- (void)_queueData:(NSDictionary *)data responseCallback:(WVJBCallback)responseCallback handlerName:(NSString*)handlerName { +- (void)_queueData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; if (responseCallback) { @@ -112,7 +112,7 @@ - (void)_flushMessageQueue { #else NSDictionary *message = [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; #endif - WVJBCallback responseCallback = NULL; + WVJBResponseCallback responseCallback = NULL; if ([message objectForKey:@"callbackId"]) { __block NSString* responseId = [message objectForKey:@"callbackId"]; responseCallback = ^(NSDictionary* data) { From c2eddcb9281f8870558e97025874f6babc39a797 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 14:34:40 -0700 Subject: [PATCH 009/342] finish up docs --- ExampleApp/ExampleAppDelegate.m | 4 +- README.md | 109 ++++++++++++++++-- .../WebViewJavascriptBridge.h | 2 +- 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/ExampleApp/ExampleAppDelegate.m b/ExampleApp/ExampleAppDelegate.m index d797dcc0..e3439a2e 100644 --- a/ExampleApp/ExampleAppDelegate.m +++ b/ExampleApp/ExampleAppDelegate.m @@ -51,8 +51,8 @@ - (void)sendMessage:(id)sender { } - (void)callHandler:(id)sender { - [self.javascriptBridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"] responseCallback:^(id data) { - NSLog(@"testJavascriptHandler responded: %@", data); + [self.javascriptBridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"] responseCallback:^(id responseData) { + NSLog(@"testJavascriptHandler responded: %@", responseData); }]; } diff --git a/README.md b/README.md index 49f2e2bf..672d8878 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ In the dialog that appears: [javascriptBridge send:@"Well hello there"]; [javascriptBridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]]; - [javascriptBridge send:@"Give me a response, will you?" responseCallback:^(id data) { - NSLog(@"I got a response! %@", data); + [javascriptBridge send:@"Give me a response, will you?" responseCallback:^(id responseData) { + NSLog(@"I got a response! %@", responseData); }]; 4) Finally, set up the javascript side of things: @@ -59,7 +59,7 @@ This lets you register named handlers for e.g. command handling. You should regi In ObjC: // Register handler - [javascriptBridge registerHandler:@"greetPerson" responseCallback:^(id data, WVJBCallback callback) { + [javascriptBridge registerHandler:@"greetPerson" handler:^(id responseData, WVJBResponseHandler callback) { callback([NSString stringWithFormat:@"Hello, %@", [data objectForKey:@"name"]]); }]; // Call javascript handlers @@ -82,15 +82,19 @@ In javascript: alert("ObjC created greeting: "+ data) }) -### iOS4 support (with JSONKit) +iOS4 support (with JSONKit) +--------------------------- WebViewJavascriptBridge uses `NSJSONSerialization` by default. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. -### ObjC API Reference +API Reference +------------- -- `[WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*) handler:(WVJBHandler)]` +### ObjC -Create a javascript bridge for the given webview. +#### `WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*)webview handler:(WVJBHandler)handler]` + +Create a javascript bridge for the given UIWebView. Example: @@ -101,7 +105,96 @@ Example: } }] -... More to come soon ... +The handler's `responseCallback` will be a block if javascript sent the message with a function responseCallback, or `nil` otherwise. + +#### `[bridge send:(id)data]` +#### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` + +Send a message to javascript. Optionally expect a response by giving a `responseCallback` block. + +Example: + + [bridge send:@"Hi"]; + [bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]]; + [bridge send:@"I expect a response!" responseCallback:^(id data) { + NSLog(@"Got response: %@", data); + }]; + +#### `[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]` + +Register a handler called `handlerName`. The javascript can then call this handler with `WebViewJavascriptBridge.callHandler("handlerName", function(response) { ... })`. + +Example: + + [bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) { + responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]); + }]; + +#### `[bridge callHandler:(NSString*)handlerName data:(id)data]` +#### `[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` + +Call the javascript handler called `handlerName`. Optionally expect a response by giving a `responseCallback` block. + +Example: + + [bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"]; + [bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) { + NSLog(@"Current UIWebView page URL is: %@", responseData); + }]; + + +### Javascript + +#### `document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReadyHandler() { ... }, false)` + +Always wait for the `WebViewJavascriptBridgeReady` DOM event before using `WebViewJavascriptBridge`. + +Example: + + document.addEventListener('WebViewJavascriptBridgeReady', function() { + // Start using WebViewJavascriptBridge + }, false) + +#### `WebViewJavascriptBridge.init(function messageHandler(data, responseCallback) { ... })` + +Initialize the WebViewJavascriptBridge. 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 `responseCallback` will be a function if ObjC sent the message with a `WVJBResponseCallback` block, or `undefined` otherwise. + +Example: + + WebViewJavascriptBridge.init(function(data, responseCallback) { + alert("Got data " + JSON.stringify(data)) + if (responseCallback) { + responseCallback("Right back atcha!") + } + }) + +#### `WebViewJavascriptBridge.send("Hi there!")` +#### `WebViewJavascriptBridge.send({ Foo:"Bar" })` +#### `WebViewJavascriptBridge.send(data, function responseCallback(responseData) { ... })` + +Send a message to ObjC. Optionally expect a response by giving a `responseCallback` function. + +Example: + + WebViewJavascriptBridge.send("Hi there!") + WebViewJavascriptBridge.send("Hi there!", function(response) { + alert("I got a response! "+JSON.stringify(response)) + }) + +#### `WebViewJavascriptBridge.registerHandler("handlerName", function(data, responseCallback) { ... })` + +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: + + WebViewJavascriptBridge.registerHandler("showAlert", function(data) { alert(data) }) + WebViewJavascriptBridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) { + responseCallback(document.location.toString()) + }) Contributors ------------ diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 7ac1ac70..8a73b38e 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -1,6 +1,6 @@ #import -typedef void (^WVJBResponseCallback)(id data); +typedef void (^WVJBResponseCallback)(id responseData); typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @class WebViewJavascriptBridge; From ff6497cdba527defddf6e31eeeb6a5fd73cf86d3 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 13 Sep 2012 14:41:10 -0700 Subject: [PATCH 010/342] Improve documentation header levels --- README.md | 60 ++++++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 672d8878..a5837dbb 100644 --- a/README.md +++ b/README.md @@ -50,49 +50,19 @@ In the dialog that appears: WebViewJavascriptBridge.send('Hello from the javascript') }, false) -5) Optional API: Registered handlers - -This lets you register named handlers for e.g. command handling. You should register handlers - -*Note:* You need to 1) register ObjC handlers before loading the UIWebView, and 2) register javascript handlers before calling `WebViewJavascriptBridge.init`. - -In ObjC: - - // Register handler - [javascriptBridge registerHandler:@"greetPerson" handler:^(id responseData, WVJBResponseHandler callback) { - callback([NSString stringWithFormat:@"Hello, %@", [data objectForKey:@"name"]]); - }]; - // Call javascript handlers - [javascriptBridge callHandler:@"showAlert" data:@"FooBar"]; - [javascriptBridge callHandler:@"getUrl" data:nil callback:^(id data) { - NSLog(@"UIWebView url is %@", data); - }]; - -In javascript: - - // Register handlers - WebViewJavascriptBridge.registerHandler('showAlert', function(data) { - alert(data) - }) - WebViewJavascriptBridge.registerHandler('getUrl', function(data, responseCallback) { - responseCallback(document.location.toString()) - }) - // Call ObjC handler - WebViewJavascriptBridge.callHandler('greetPerson', { name:'Marcus' }, function responseCallback(data) { - alert("ObjC created greeting: "+ data) - }) - iOS4 support (with JSONKit) --------------------------- - WebViewJavascriptBridge uses `NSJSONSerialization` by default. If you need iOS 4 support then you can use [JSONKit](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. +*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](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. API Reference ------------- ### ObjC -#### `WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*)webview handler:(WVJBHandler)handler]` +##### `[WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*)webview handler:(WVJBHandler)handler]` Create a javascript bridge for the given UIWebView. @@ -107,8 +77,8 @@ Example: The handler's `responseCallback` will be a block if javascript sent the message with a function responseCallback, or `nil` otherwise. -#### `[bridge send:(id)data]` -#### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` +##### `[bridge send:(id)data]` +##### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` Send a message to javascript. Optionally expect a response by giving a `responseCallback` block. @@ -120,7 +90,7 @@ Example: NSLog(@"Got response: %@", data); }]; -#### `[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]` +##### `[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]` Register a handler called `handlerName`. The javascript can then call this handler with `WebViewJavascriptBridge.callHandler("handlerName", function(response) { ... })`. @@ -130,8 +100,8 @@ Example: responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]); }]; -#### `[bridge callHandler:(NSString*)handlerName data:(id)data]` -#### `[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` +##### `[bridge callHandler:(NSString*)handlerName data:(id)data]` +##### `[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. @@ -145,7 +115,7 @@ Example: ### Javascript -#### `document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReadyHandler() { ... }, false)` +##### `document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReadyHandler() { ... }, false)` Always wait for the `WebViewJavascriptBridgeReady` DOM event before using `WebViewJavascriptBridge`. @@ -155,7 +125,7 @@ Example: // Start using WebViewJavascriptBridge }, false) -#### `WebViewJavascriptBridge.init(function messageHandler(data, responseCallback) { ... })` +##### `WebViewJavascriptBridge.init(function messageHandler(data, responseCallback) { ... })` Initialize the WebViewJavascriptBridge. This should be called inside of the `'WebViewJavascriptBridgeReady'` event handler. @@ -172,9 +142,9 @@ Example: } }) -#### `WebViewJavascriptBridge.send("Hi there!")` -#### `WebViewJavascriptBridge.send({ Foo:"Bar" })` -#### `WebViewJavascriptBridge.send(data, function responseCallback(responseData) { ... })` +##### `WebViewJavascriptBridge.send("Hi there!")` +##### `WebViewJavascriptBridge.send({ Foo:"Bar" })` +##### `WebViewJavascriptBridge.send(data, function responseCallback(responseData) { ... })` Send a message to ObjC. Optionally expect a response by giving a `responseCallback` function. @@ -185,7 +155,7 @@ Example: alert("I got a response! "+JSON.stringify(response)) }) -#### `WebViewJavascriptBridge.registerHandler("handlerName", function(data, responseCallback) { ... })` +##### `WebViewJavascriptBridge.registerHandler("handlerName", function(data, responseCallback) { ... })` 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) { ... }]` From 7b8d0e719bd86668a6ad650157b809bc7988625b Mon Sep 17 00:00:00 2001 From: ckmcc Date: Tue, 18 Sep 2012 20:59:19 -0500 Subject: [PATCH 011/342] Replace `WVJBCallback` with `WVJBResponseCallback` --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a5837dbb..dac274ca 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ In the dialog that appears: 3) Instantiate a UIWebView and a WebViewJavascriptBridge: UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; - WebViewJavascriptBridge* javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback callback) { + WebViewJavascriptBridge* javascriptBridge = [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBResponseCallback callback) { NSLog(@"Received message from javascript: %@", data); }]; @@ -68,7 +68,7 @@ Create a javascript bridge for the given UIWebView. Example: - [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBCallback responseCallback) { + [WebViewJavascriptBridge javascriptBridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"Received message from javascript: %@", data); if (responseCallback) { responseCallback(@"Right back atcha") From 8ac33bfcb26d48de8668c0077eb61a03426702fc Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 18 Sep 2012 19:34:12 -0700 Subject: [PATCH 012/342] Document the bridge constructor with a UIWebViewDelegate given, and change the signature so as to always put the handler last --- README.md | 6 ++++++ WebViewJavascriptBridge/WebViewJavascriptBridge.h | 2 +- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dac274ca..a9af9b8a 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ API Reference ### ObjC ##### `[WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*)webview handler:(WVJBHandler)handler]` +##### `[WebViewJavascriptBridge javascriptBridgeForWebView:(UIWebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]` Create a javascript bridge for the given UIWebView. @@ -74,9 +75,14 @@ Example: responseCallback(@"Right back atcha") } }] + + [WebViewJavascriptBridge javascriptBridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBCallback responseCallback) { /* ... */ }]; The handler's `responseCallback` will be a block if javascript sent the message with a function responseCallback, or `nil` otherwise. +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). + + ##### `[bridge send:(id)data]` ##### `[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]` diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 8a73b38e..db053b7d 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -8,7 +8,7 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridge : NSObject + (id)javascriptBridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; -+ (id)javascriptBridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler webViewDelegate:(id )webViewDelegate; ++ (id)javascriptBridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; - (void)send:(id)message; - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 301b876e..fb2d39a7 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -27,10 +27,10 @@ @implementation WebViewJavascriptBridge static NSString *QUEUE_HAS_MESSAGE = @"__WVJB_QUEUE_MESSAGE__"; + (id)javascriptBridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { - return [self javascriptBridgeForWebView:webView handler:handler webViewDelegate:nil]; + return [self javascriptBridgeForWebView:webView webViewDelegate:nil handler:handler]; } -+ (id)javascriptBridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)messageHandler webViewDelegate:(id)webViewDelegate { ++ (id)javascriptBridgeForWebView:(UIWebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; bridge.messageHandler = messageHandler; bridge.startupMessageQueue = [NSMutableArray array]; From ac1a56ec0bfc8a1e37601a0859d7a069b6523de0 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 18 Sep 2012 19:55:39 -0700 Subject: [PATCH 013/342] Fix bug found by @drewburch that would cause response messages sent from ObjC to be double-wrapped --- .../WebViewJavascriptBridge.m | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index fb2d39a7..19bf7c26 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -15,7 +15,8 @@ @interface WebViewJavascriptBridge () @property (nonatomic, copy) WVJBHandler messageHandler; - (void)_flushMessageQueue; -- (void)_queueData:(NSDictionary*)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; +- (void)_sendData:(NSDictionary*)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; +- (void)_queueMessage:(NSDictionary*)message; - (void)_dispatchMessage:(NSDictionary*)message; @end @@ -48,7 +49,7 @@ - (void)send:(NSDictionary *)data { } - (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback { - [self _queueData:data responseCallback:responseCallback handlerName:nil]; + [self _sendData:data responseCallback:responseCallback handlerName:nil]; } - (void)callHandler:(NSString *)handlerName { @@ -60,14 +61,14 @@ - (void)callHandler:(NSString *)handlerName data:(id)data { } - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [self _queueData:data responseCallback:responseCallback handlerName:handlerName]; + [self _sendData:data responseCallback:responseCallback handlerName:handlerName]; } - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { [self.messageHandlers setObject:handler forKey:handlerName]; } -- (void)_queueData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { +- (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; if (responseCallback) { @@ -79,7 +80,10 @@ - (void)_queueData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)r if (handlerName) { [message setObject:handlerName forKey:@"handlerName"]; } - + [self _queueMessage:message]; +} + +- (void)_queueMessage:(NSDictionary *)message { if (self.startupMessageQueue) { [self.startupMessageQueue addObject:message]; } else { @@ -116,8 +120,8 @@ - (void)_flushMessageQueue { if ([message objectForKey:@"callbackId"]) { __block NSString* responseId = [message objectForKey:@"callbackId"]; responseCallback = ^(NSDictionary* data) { - NSDictionary* response = [NSDictionary dictionaryWithObjectsAndKeys: responseId, @"responseId", data, @"data", nil]; - [self send:response]; + NSDictionary* responseMessage = [NSDictionary dictionaryWithObjectsAndKeys: responseId, @"responseId", data, @"data", nil]; + [self _queueMessage:responseMessage]; }; } From 942c507fb3c2ddaa57684ce9331e6d9740c9e7d4 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 18 Sep 2012 19:55:52 -0700 Subject: [PATCH 014/342] note intended v2 changes in Changelog --- Changelog | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 91094d00..952a3051 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,10 @@ -intended v0.0.1 +intended v2.0.0 ++ Messages are objects instead of strings. Supports NSDictionary*/Objects, NSArray*/Arrays, NSNumber*/Number & NSString*/String. ++ Messages are encoded with NSJSONSerialization. Optional fallback to JSONKit for iOS 4 support. ++ Messages can expect responses. A message received with an expected response is accompanied by a WVJBResponseCallback/Function. ++ Handlers can be registered by name, and called with data and an optional expected response. + +v0.0.1 + ObjC: A WebViewJavascriptBridge class (a UIWebViewDelegate) that enables message passing to and from the JS + ObjC: A protocol called WebViewJavascriptBridgeDelegate that lets you handle messages received from the JS + JS: Event when the bridge is ready - document.addEventListener('WebViewJavascriptBridgeReady', function() {}, false) From f179fcf468f6640b0e6fb01cc838ef33ada640a2 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 18 Sep 2012 20:07:29 -0700 Subject: [PATCH 015/342] improve example app styling and example functionality --- ExampleApp/ExampleApp.html | 22 +++++++++++++++------- ExampleApp/ExampleAppDelegate.m | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ExampleApp/ExampleApp.html b/ExampleApp/ExampleApp.html index 7bbbde8b..35ed30bb 100644 --- a/ExampleApp/ExampleApp.html +++ b/ExampleApp/ExampleApp.html @@ -1,16 +1,21 @@ - +

Javascript Bridge Demo

+
+ diff --git a/ExampleApp-OSX/en.lproj/Credits.rtf b/ExampleApp-OSX/en.lproj/Credits.rtf new file mode 100644 index 00000000..46576ef2 --- /dev/null +++ b/ExampleApp-OSX/en.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/ExampleApp-OSX/en.lproj/InfoPlist.strings b/ExampleApp-OSX/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/ExampleApp-OSX/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/ExampleApp-OSX/en.lproj/MainMenu.xib b/ExampleApp-OSX/en.lproj/MainMenu.xib new file mode 100644 index 00000000..b4989b1d --- /dev/null +++ b/ExampleApp-OSX/en.lproj/MainMenu.xib @@ -0,0 +1,3614 @@ + + + + 1070 + 11E53 + 2844 + 1138.47 + 569.00 + + 2844 + 1810 + + + IBNSLayoutConstraint + NSButton + NSButtonCell + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + WebView + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + ExampleApp-OSX + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + ExampleApp-OSX + + + + About ExampleApp-OSX + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide ExampleApp-OSX + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit ExampleApp-OSX + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + + + Font + + 2147483647 + + + submenuAction: + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligatures + + 2147483647 + + + submenuAction: + + Ligatures + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + ExampleApp-OSX Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 360}} + 1954021376 + ExampleApp-OSX + NSWindow + + + + + 256 + + + + 256 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + {{0, 37}, {480, 323}} + + + + _NS:9 + + + + + + + + + + + YES + YES + + + + 268 + {{20, 10}, {97, 19}} + + + + _NS:9 + YES + + -2080374784 + 134217728 + Send message + + LucidaGrande + 12 + 16 + + _NS:9 + + -2038153216 + 164 + + + 400 + 75 + + + + + 268 + {{125, 10}, {86, 19}} + + + _NS:9 + YES + + -2080374784 + 134217728 + Call Handler + + _NS:9 + + -2038153216 + 164 + + + 400 + 75 + + + + {480, 360} + + + + + {{0, 0}, {1280, 778}} + {10000000000000, 10000000000000} + YES + + + AppDelegate + + + NSFontManager + + + + 256 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + {254, 200} + + + + _NS:9 + + + + YES + YES + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + window + + + + 532 + + + + webView + + + + 543 + + + + sendMessage: + + + + 555 + + + + callHandler: + + + + 556 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + + + + 372 + + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 494 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 536 + + + + + 8 + 0 + + 0 + 1 + + 323 + + 1000 + + 3 + 9 + 1 + + + + + + 539 + + + + + 540 + + + + + 542 + + + + + 544 + + + + + 545 + + + + + + + + 546 + + + + + 550 + + + + + 551 + + + + + + + + 552 + + + + + 554 + + + + + 557 + + + + + 558 + + + + + 559 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 559 + + + + + AppDelegate + NSObject + + id + id + + + + callHandler: + id + + + sendMessage: + id + + + + WebView + NSWindow + + + + webView + WebView + + + window + NSWindow + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + NSLayoutConstraint + NSObject + + IBProjectSource + ./Classes/NSLayoutConstraint.h + + + + + 0 + IBCocoaFramework + YES + 3 + + {11, 11} + {10, 3} + + YES + + diff --git a/ExampleApp-OSX/main.m b/ExampleApp-OSX/main.m new file mode 100644 index 00000000..ae7b871a --- /dev/null +++ b/ExampleApp-OSX/main.m @@ -0,0 +1,14 @@ +// +// main.m +// ExampleApp-OSX +// +// Created by Antoine Lagadec on 07/04/13. +// Copyright (c) 2013 Antoine Lagadec. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.h new file mode 100644 index 00000000..9a8b2f4f --- /dev/null +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.h @@ -0,0 +1,20 @@ +// +// WebViewJavascriptBridge+OSX.h +// ExampleApp-OSX +// +// Created by Antoine Lagadec on 07/04/13. +// Copyright (c) 2013 Antoine Lagadec. All rights reserved. +// + +#import +#import "WebViewJavascriptBridgeAbstract.h" + +@interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract + +@property (nonatomic, strong) WebView *webView; +@property (nonatomic, strong) id webViewDelegate; + ++ (id)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; ++ (id)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; + +@end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.m new file mode 100644 index 00000000..02ee2ed2 --- /dev/null +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.m @@ -0,0 +1,96 @@ +// +// WebViewJavascriptBridge+OSX.m +// ExampleApp-OSX +// +// Created by Antoine Lagadec on 07/04/13. +// Copyright (c) 2013 Antoine Lagadec. All rights reserved. +// + +#import "WebViewJavascriptBridge_OSX.h" + +@implementation WebViewJavascriptBridge + ++ (id)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { + return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; +} + ++ (id)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { + WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + bridge.messageHandler = messageHandler; + bridge.webView = webView; + bridge.webViewDelegate = webViewDelegate; + bridge.messageHandlers = [NSMutableDictionary dictionary]; + [bridge reset]; + + bridge.webView.frameLoadDelegate = bridge; + bridge.webView.resourceLoadDelegate = bridge; + bridge.webView.policyDelegate = bridge; + + return bridge; +} + +- (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame +{ + if (webView != self.webView) { return; } + + if (![[self.webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + [self.webView stringByEvaluatingJavaScriptFromString:js]; + } + + if (self.startupMessageQueue) { + for (id queuedMessage in self.startupMessageQueue) { + [self _dispatchMessage:queuedMessage]; + } + self.startupMessageQueue = nil; + } + + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) { + [self.webViewDelegate webView:webView didFinishLoadForFrame:frame]; + } +} + +- (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + if (webView != self.webView) { return; } + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { + [self.webViewDelegate webView:self.webView didFailLoadWithError:error forFrame:frame]; + } +} + +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener +{ + if (webView != self.webView) { [listener use]; } + NSURL *url = [request URL]; + if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { + if ([[url host] isEqualToString:kQueueHasMessage]) { + [self _flushMessageQueue]; + } else { + NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); + } + [listener ignore]; + } else if ([self.webView resourceLoadDelegate] + && [self.webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { + [self.webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; + } else { + [listener use]; + } +} + +- (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { + if (webView != self.webView) { return; } + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { + [self.webViewDelegate webView:webView didCommitLoadForFrame:frame]; + } +} + +- (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { + if (webView != self.webView) { return request; } + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { + return [self.webViewDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; + } + + return request; +} + +@end From 23647a1b20faa0a33934a500de13f296d4b56e2a Mon Sep 17 00:00:00 2001 From: Antoine Lagadec Date: Sun, 7 Apr 2013 15:33:33 +0200 Subject: [PATCH 067/342] Add a workspace for testing facility --- ExampleApp-OSX.xcodeproj/project.pbxproj | 56 +++++++--------- ExampleApp-OSX/en.lproj/Credits.rtf | 29 -------- ExampleApp-iOS.xcodeproj/project.pbxproj | 58 +++++++++------- ExampleApp-iOS/ExampleApp.html | 66 ------------------- .../ExampleApp.html => ExampleApp.html | 0 .../contents.xcworkspacedata | 10 +++ 6 files changed, 65 insertions(+), 154 deletions(-) delete mode 100644 ExampleApp-OSX/en.lproj/Credits.rtf delete mode 100644 ExampleApp-iOS/ExampleApp.html rename ExampleApp-OSX/ExampleApp.html => ExampleApp.html (100%) create mode 100644 WebViewJavascriptBridge.xcworkspace/contents.xcworkspacedata diff --git a/ExampleApp-OSX.xcodeproj/project.pbxproj b/ExampleApp-OSX.xcodeproj/project.pbxproj index 94d32ce7..16b0d16b 100644 --- a/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -10,14 +10,13 @@ 2CA045DA171178E5006DEE8B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA045D9171178E5006DEE8B /* Cocoa.framework */; }; 2CA045E4171178E6006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045E2171178E6006DEE8B /* InfoPlist.strings */; }; 2CA045E6171178E6006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045E5171178E6006DEE8B /* main.m */; }; - 2CA045EA171178E6006DEE8B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045E8171178E6006DEE8B /* Credits.rtf */; }; 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045EC171178E6006DEE8B /* AppDelegate.m */; }; 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045EE171178E6006DEE8B /* MainMenu.xib */; }; - 2CA045FE17117A69006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045FC17117A69006DEE8B /* WebViewJavascriptBridge.js.txt */; }; - 2CA0460317117A84006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA0460217117A84006DEE8B /* WebViewJavascriptBridge_OSX.m */; }; 2CA0460517117B56006DEE8B /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA0460417117B56006DEE8B /* WebKit.framework */; }; - 2CA0460A17118B08006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0460917118B08006DEE8B /* ExampleApp.html */; }; - 2CA046161711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046151711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; + 2CA046531711AC29006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */; }; + 2CA046551711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */; }; + 2CA046561711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; + 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465D1711AC96006DEE8B /* ExampleApp.html */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -30,17 +29,16 @@ 2CA045E3171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 2CA045E5171178E6006DEE8B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 2CA045E7171178E6006DEE8B /* ExampleApp-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-OSX-Prefix.pch"; sourceTree = ""; }; - 2CA045E9171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 2CA045EB171178E6006DEE8B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 2CA045EC171178E6006DEE8B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 2CA045EF171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - 2CA045FC17117A69006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CA0460117117A84006DEE8B /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; - 2CA0460217117A84006DEE8B /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; 2CA0460417117B56006DEE8B /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 2CA0460917118B08006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; - 2CA046141711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CA046151711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2CA0464F1711AC29006DEE8B /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; + 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; + 2CA046511711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; + 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2CA0465D1711AC96006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; name = ExampleApp.html; path = ../ExampleApp.html; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -96,11 +94,11 @@ 2CA045DF171178E5006DEE8B /* ExampleApp-OSX */ = { isa = PBXGroup; children = ( + 2CA0465D1711AC96006DEE8B /* ExampleApp.html */, + 2CA0464B1711AC29006DEE8B /* WebViewJavascriptBridge */, 2CA045EB171178E6006DEE8B /* AppDelegate.h */, 2CA045EC171178E6006DEE8B /* AppDelegate.m */, 2CA045EE171178E6006DEE8B /* MainMenu.xib */, - 2CA0460917118B08006DEE8B /* ExampleApp.html */, - 2CA045FA17117A69006DEE8B /* WebViewJavascriptBridge */, 2CA045E0171178E6006DEE8B /* Supporting Files */, ); path = "ExampleApp-OSX"; @@ -113,19 +111,18 @@ 2CA045E2171178E6006DEE8B /* InfoPlist.strings */, 2CA045E5171178E6006DEE8B /* main.m */, 2CA045E7171178E6006DEE8B /* ExampleApp-OSX-Prefix.pch */, - 2CA045E8171178E6006DEE8B /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; - 2CA045FA17117A69006DEE8B /* WebViewJavascriptBridge */ = { + 2CA0464B1711AC29006DEE8B /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 2CA046141711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.h */, - 2CA046151711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.m */, - 2CA045FC17117A69006DEE8B /* WebViewJavascriptBridge.js.txt */, - 2CA0460117117A84006DEE8B /* WebViewJavascriptBridge_OSX.h */, - 2CA0460217117A84006DEE8B /* WebViewJavascriptBridge_OSX.m */, + 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */, + 2CA0464F1711AC29006DEE8B /* WebViewJavascriptBridge_OSX.h */, + 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */, + 2CA046511711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.h */, + 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */, ); path = WebViewJavascriptBridge; sourceTree = SOURCE_ROOT; @@ -182,10 +179,9 @@ buildActionMask = 2147483647; files = ( 2CA045E4171178E6006DEE8B /* InfoPlist.strings in Resources */, - 2CA045EA171178E6006DEE8B /* Credits.rtf in Resources */, 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */, - 2CA045FE17117A69006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, - 2CA0460A17118B08006DEE8B /* ExampleApp.html in Resources */, + 2CA046531711AC29006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, + 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -198,8 +194,8 @@ files = ( 2CA045E6171178E6006DEE8B /* main.m in Sources */, 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */, - 2CA0460317117A84006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */, - 2CA046161711A1CC006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2CA046551711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */, + 2CA046561711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -214,14 +210,6 @@ name = InfoPlist.strings; sourceTree = ""; }; - 2CA045E8171178E6006DEE8B /* Credits.rtf */ = { - isa = PBXVariantGroup; - children = ( - 2CA045E9171178E6006DEE8B /* en */, - ); - name = Credits.rtf; - sourceTree = ""; - }; 2CA045EE171178E6006DEE8B /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/ExampleApp-OSX/en.lproj/Credits.rtf b/ExampleApp-OSX/en.lproj/Credits.rtf deleted file mode 100644 index 46576ef2..00000000 --- a/ExampleApp-OSX/en.lproj/Credits.rtf +++ /dev/null @@ -1,29 +0,0 @@ -{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} -{\colortbl;\red255\green255\blue255;} -\paperw9840\paperh8400 -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural - -\f0\b\fs24 \cf0 Engineering: -\b0 \ - Some people\ -\ - -\b Human Interface Design: -\b0 \ - Some other people\ -\ - -\b Testing: -\b0 \ - Hopefully not nobody\ -\ - -\b Documentation: -\b0 \ - Whoever\ -\ - -\b With special thanks to: -\b0 \ - Mom\ -} diff --git a/ExampleApp-iOS.xcodeproj/project.pbxproj b/ExampleApp-iOS.xcodeproj/project.pbxproj index 455727cb..8338241b 100644 --- a/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -8,12 +8,12 @@ /* Begin PBXBuildFile section */ 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045B717117439006DEE8B /* InfoPlist.strings */; }; - 2CA045C117117439006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045BB17117439006DEE8B /* ExampleApp.html */; }; 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; }; 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; }; - 2CA045C81711745D006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045C61711745D006DEE8B /* WebViewJavascriptBridge.js.txt */; }; - 2CA045C91711745D006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045C71711745D006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; - 2CA0460817117BF9006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA0460717117BF9006DEE8B /* WebViewJavascriptBridge_iOS.m */; }; + 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */; }; + 2CA046671711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */; }; + 2CA046681711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */; }; + 2CA0466A1711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; }; 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC11602563600548120 /* Foundation.framework */; }; 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC31602563600548120 /* CoreGraphics.framework */; }; @@ -24,15 +24,15 @@ 2CA045B817117439006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ExampleApp-iOS-Info.plist"; sourceTree = ""; }; 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-iOS-Prefix.pch"; sourceTree = ""; }; - 2CA045BB17117439006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; }; 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; 2CA045BE17117439006DEE8B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2CA045C51711745D006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CA045C61711745D006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CA045C71711745D006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; - 2CA0460617117BF9006DEE8B /* WebViewJavascriptBridge_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_iOS.h; sourceTree = ""; }; - 2CA0460717117BF9006DEE8B /* WebViewJavascriptBridge_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_iOS.m; sourceTree = ""; }; + 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; + 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2CA046611711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_iOS.h; sourceTree = ""; }; + 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_iOS.m; sourceTree = ""; }; + 2CA046651711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; + 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 2CEB3EC11602563600548120 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -57,26 +57,34 @@ 2CA045B617117439006DEE8B /* ExampleApp-iOS */ = { isa = PBXGroup; children = ( - 2CA045C41711745D006DEE8B /* WebViewJavascriptBridge */, + 2CA0465F1711ACC2006DEE8B /* WebViewJavascriptBridge */, + 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, + 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, + 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, + 2CA046211711A94E006DEE8B /* Supporting Files */, + ); + path = "ExampleApp-iOS"; + sourceTree = ""; + }; + 2CA046211711A94E006DEE8B /* Supporting Files */ = { + isa = PBXGroup; + children = ( 2CA045B717117439006DEE8B /* InfoPlist.strings */, 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */, 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */, - 2CA045BB17117439006DEE8B /* ExampleApp.html */, - 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, - 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, 2CA045BE17117439006DEE8B /* main.m */, ); - path = "ExampleApp-iOS"; + name = "Supporting Files"; sourceTree = ""; }; - 2CA045C41711745D006DEE8B /* WebViewJavascriptBridge */ = { + 2CA0465F1711ACC2006DEE8B /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 2CA045C51711745D006DEE8B /* WebViewJavascriptBridgeAbstract.h */, - 2CA045C61711745D006DEE8B /* WebViewJavascriptBridge.js.txt */, - 2CA045C71711745D006DEE8B /* WebViewJavascriptBridgeAbstract.m */, - 2CA0460617117BF9006DEE8B /* WebViewJavascriptBridge_iOS.h */, - 2CA0460717117BF9006DEE8B /* WebViewJavascriptBridge_iOS.m */, + 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */, + 2CA046611711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.h */, + 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */, + 2CA046651711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.h */, + 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */, ); path = WebViewJavascriptBridge; sourceTree = SOURCE_ROOT; @@ -162,8 +170,8 @@ files = ( 2CF988CE170E0BA500CA0CC7 /* Default-568h@2x.png in Resources */, 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */, - 2CA045C117117439006DEE8B /* ExampleApp.html in Resources */, - 2CA045C81711745D006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, + 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */, + 2CA046671711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -176,8 +184,8 @@ files = ( 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, - 2CA045C91711745D006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, - 2CA0460817117BF9006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */, + 2CA046681711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */, + 2CA0466A1711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ExampleApp-iOS/ExampleApp.html b/ExampleApp-iOS/ExampleApp.html deleted file mode 100644 index 5a12d4d2..00000000 --- a/ExampleApp-iOS/ExampleApp.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -

WebViewJavascriptBridge Demo

- -
- diff --git a/ExampleApp-OSX/ExampleApp.html b/ExampleApp.html similarity index 100% rename from ExampleApp-OSX/ExampleApp.html rename to ExampleApp.html diff --git a/WebViewJavascriptBridge.xcworkspace/contents.xcworkspacedata b/WebViewJavascriptBridge.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..2b523419 --- /dev/null +++ b/WebViewJavascriptBridge.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + From c4fbcd6182be55c17f2bdad43b72ac5ca554ca70 Mon Sep 17 00:00:00 2001 From: Antoine Lagadec Date: Sun, 7 Apr 2013 15:53:56 +0200 Subject: [PATCH 068/342] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b1ead06e..edccdc15 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,13 @@ WebViewJavascriptBridge is used by a range of companies and projects. This list - [EverTrue](http://www.evertrue.com/) - [Game Insight](http://www.game-insight.com/) - [Altralogica](http://www.altralogica.it) +- [Sush.io](http://www.sush.io) - Flutterby Labs - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) Are you using WebViewJavascript at your company? Add it and send us a pull request! -Setup & Examples +Setup & Examples (iOS) ---------------- Just open the Xcode project and hit run to see ExampleApp run. @@ -28,10 +29,11 @@ To use a WebViewJavascriptBridge in your own project: 1) 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" + - Delete OSX files. 2) Import the header file: - #import "WebViewJavascriptBridge.h" + #import "WebViewJavascriptBridge_iOS.h" 3) Instantiate a UIWebView and a WebViewJavascriptBridge: From 5775ebb7533096d0d3d1d509ef02f81be5ebe30d Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 18 Apr 2013 17:10:32 -0700 Subject: [PATCH 069/342] add disableLogging --- WebViewJavascriptBridge/WebViewJavascriptBridge.h | 1 + WebViewJavascriptBridge/WebViewJavascriptBridge.m | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 7eeaee3d..c052ee33 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -7,6 +7,7 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); + (id)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; + (id)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; + (void)enableLogging; ++ (void)disableLogging; - (void)send:(id)message; - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index bf5f9583..ae375fb1 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -45,8 +45,9 @@ + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id Date: Tue, 23 Apr 2013 18:11:21 -0700 Subject: [PATCH 070/342] Reorganize files so that: 1) including WVJB in an OSX or iOS project is simply dragging the one corresponding folder into your project (WebViewJavascriptBridge_iOS/OSX respectively), and 2) put all the example app contents in a single directory --- .../ExampleApp-OSX.xcodeproj}/project.pbxproj | 51 +++++++++------- .../ExampleApp-OSX}/AppDelegate.h | 0 .../ExampleApp-OSX}/AppDelegate.m | 0 .../ExampleApp-OSX}/ExampleApp-OSX-Info.plist | 0 .../ExampleApp-OSX}/ExampleApp-OSX-Prefix.pch | 0 .../en.lproj/InfoPlist.strings | 0 .../ExampleApp-OSX}/en.lproj/MainMenu.xib | 0 .../ExampleApp-OSX}/main.m | 0 .../ExampleApp-iOS.xcodeproj}/project.pbxproj | 57 ++++++++++-------- .../ExampleApp-iOS/Default-568h@2x.png | Bin .../ExampleApp-iOS}/ExampleApp-iOS-Info.plist | 0 .../ExampleApp-iOS}/ExampleApp-iOS-Prefix.pch | 0 .../ExampleApp-iOS}/ExampleAppDelegate.h | 0 .../ExampleApp-iOS}/ExampleAppDelegate.m | 0 .../en.lproj/InfoPlist.strings | 0 .../ExampleApp-iOS}/main.m | 0 .../ExampleApp.html | 0 .../WebViewJavascriptBridge.js.txt | 0 .../WebViewJavascriptBridgeAbstract.h | 0 .../WebViewJavascriptBridgeAbstract.m | 0 .../WebViewJavascriptAbstract | 1 + .../WebViewJavascriptBridge_OSX.h | 0 .../WebViewJavascriptBridge_OSX.m | 0 .../WebViewJavascriptAbstract | 1 + .../WebViewJavascriptBridge_iOS.h | 0 .../WebViewJavascriptBridge_iOS.m | 0 26 files changed, 65 insertions(+), 45 deletions(-) rename {ExampleApp-OSX.xcodeproj => Example Apps/ExampleApp-OSX.xcodeproj}/project.pbxproj (86%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/AppDelegate.h (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/AppDelegate.m (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/ExampleApp-OSX-Info.plist (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/ExampleApp-OSX-Prefix.pch (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/en.lproj/InfoPlist.strings (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/en.lproj/MainMenu.xib (100%) rename {ExampleApp-OSX => Example Apps/ExampleApp-OSX}/main.m (100%) rename {ExampleApp-iOS.xcodeproj => Example Apps/ExampleApp-iOS.xcodeproj}/project.pbxproj (83%) rename Default-568h@2x.png => Example Apps/ExampleApp-iOS/Default-568h@2x.png (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/ExampleApp-iOS-Info.plist (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/ExampleApp-iOS-Prefix.pch (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/ExampleAppDelegate.h (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/ExampleAppDelegate.m (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/en.lproj/InfoPlist.strings (100%) rename {ExampleApp-iOS => Example Apps/ExampleApp-iOS}/main.m (100%) rename ExampleApp.html => Example Apps/ExampleApp.html (100%) rename {WebViewJavascriptBridge => WebViewJavascriptBridgeAbstract}/WebViewJavascriptBridge.js.txt (100%) rename {WebViewJavascriptBridge => WebViewJavascriptBridgeAbstract}/WebViewJavascriptBridgeAbstract.h (100%) rename {WebViewJavascriptBridge => WebViewJavascriptBridgeAbstract}/WebViewJavascriptBridgeAbstract.m (100%) create mode 120000 WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract rename {WebViewJavascriptBridge => WebViewJavascriptBridge_OSX}/WebViewJavascriptBridge_OSX.h (100%) rename {WebViewJavascriptBridge => WebViewJavascriptBridge_OSX}/WebViewJavascriptBridge_OSX.m (100%) create mode 120000 WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract rename {WebViewJavascriptBridge => WebViewJavascriptBridge_iOS}/WebViewJavascriptBridge_iOS.h (100%) rename {WebViewJavascriptBridge => WebViewJavascriptBridge_iOS}/WebViewJavascriptBridge_iOS.m (100%) diff --git a/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj similarity index 86% rename from ExampleApp-OSX.xcodeproj/project.pbxproj rename to Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index 16b0d16b..5e5e13ab 100644 --- a/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -13,10 +13,10 @@ 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045EC171178E6006DEE8B /* AppDelegate.m */; }; 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045EE171178E6006DEE8B /* MainMenu.xib */; }; 2CA0460517117B56006DEE8B /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA0460417117B56006DEE8B /* WebKit.framework */; }; - 2CA046531711AC29006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */; }; - 2CA046551711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */; }; - 2CA046561711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465D1711AC96006DEE8B /* ExampleApp.html */; }; + 2CAB8695172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */; }; + 2CAB8696172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */; }; + 2CAB8697172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -33,12 +33,12 @@ 2CA045EC171178E6006DEE8B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 2CA045EF171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 2CA0460417117B56006DEE8B /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CA0464F1711AC29006DEE8B /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; - 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; - 2CA046511711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; - 2CA0465D1711AC96006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; name = ExampleApp.html; path = ../ExampleApp.html; sourceTree = ""; }; + 2CA0465D1711AC96006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ExampleApp.html; path = ../ExampleApp.html; sourceTree = ""; }; + 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2CAB8691172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; + 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2CAB8693172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; + 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -95,10 +95,10 @@ isa = PBXGroup; children = ( 2CA0465D1711AC96006DEE8B /* ExampleApp.html */, - 2CA0464B1711AC29006DEE8B /* WebViewJavascriptBridge */, 2CA045EB171178E6006DEE8B /* AppDelegate.h */, 2CA045EC171178E6006DEE8B /* AppDelegate.m */, 2CA045EE171178E6006DEE8B /* MainMenu.xib */, + 2CAB868E172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX */, 2CA045E0171178E6006DEE8B /* Supporting Files */, ); path = "ExampleApp-OSX"; @@ -115,17 +115,26 @@ name = "Supporting Files"; sourceTree = ""; }; - 2CA0464B1711AC29006DEE8B /* WebViewJavascriptBridge */ = { + 2CAB868E172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX */ = { isa = PBXGroup; children = ( - 2CA0464C1711AC29006DEE8B /* WebViewJavascriptBridge.js.txt */, - 2CA0464F1711AC29006DEE8B /* WebViewJavascriptBridge_OSX.h */, - 2CA046501711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m */, - 2CA046511711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.h */, - 2CA046521711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m */, + 2CAB868F172766DF00BD9ED1 /* WebViewJavascriptAbstract */, + 2CAB8693172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.h */, + 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */, ); - path = WebViewJavascriptBridge; - sourceTree = SOURCE_ROOT; + name = WebViewJavascriptBridge_OSX; + path = ../../WebViewJavascriptBridge_OSX; + sourceTree = ""; + }; + 2CAB868F172766DF00BD9ED1 /* WebViewJavascriptAbstract */ = { + isa = PBXGroup; + children = ( + 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */, + 2CAB8691172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.h */, + 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */, + ); + path = WebViewJavascriptAbstract; + sourceTree = ""; }; /* End PBXGroup section */ @@ -180,8 +189,8 @@ files = ( 2CA045E4171178E6006DEE8B /* InfoPlist.strings in Resources */, 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */, - 2CA046531711AC29006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */, + 2CAB8695172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -194,8 +203,8 @@ files = ( 2CA045E6171178E6006DEE8B /* main.m in Sources */, 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */, - 2CA046551711AC29006DEE8B /* WebViewJavascriptBridge_OSX.m in Sources */, - 2CA046561711AC29006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2CAB8696172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2CAB8697172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ExampleApp-OSX/AppDelegate.h b/Example Apps/ExampleApp-OSX/AppDelegate.h similarity index 100% rename from ExampleApp-OSX/AppDelegate.h rename to Example Apps/ExampleApp-OSX/AppDelegate.h diff --git a/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m similarity index 100% rename from ExampleApp-OSX/AppDelegate.m rename to Example Apps/ExampleApp-OSX/AppDelegate.m diff --git a/ExampleApp-OSX/ExampleApp-OSX-Info.plist b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist similarity index 100% rename from ExampleApp-OSX/ExampleApp-OSX-Info.plist rename to Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist diff --git a/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch similarity index 100% rename from ExampleApp-OSX/ExampleApp-OSX-Prefix.pch rename to Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch diff --git a/ExampleApp-OSX/en.lproj/InfoPlist.strings b/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings similarity index 100% rename from ExampleApp-OSX/en.lproj/InfoPlist.strings rename to Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings diff --git a/ExampleApp-OSX/en.lproj/MainMenu.xib b/Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib similarity index 100% rename from ExampleApp-OSX/en.lproj/MainMenu.xib rename to Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib diff --git a/ExampleApp-OSX/main.m b/Example Apps/ExampleApp-OSX/main.m similarity index 100% rename from ExampleApp-OSX/main.m rename to Example Apps/ExampleApp-OSX/main.m diff --git a/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj similarity index 83% rename from ExampleApp-iOS.xcodeproj/project.pbxproj rename to Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 8338241b..6a694a05 100644 --- a/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -11,13 +11,13 @@ 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; }; 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; }; 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */; }; - 2CA046671711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */; }; - 2CA046681711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */; }; - 2CA0466A1711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */; }; + 2CAB868B172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */; }; + 2CAB868C172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */; }; + 2CAB868D172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */; }; + 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */; }; 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; }; 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC11602563600548120 /* Foundation.framework */; }; 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC31602563600548120 /* CoreGraphics.framework */; }; - 2CF988CE170E0BA500CA0CC7 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CF988CD170E0BA500CA0CC7 /* Default-568h@2x.png */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -28,16 +28,16 @@ 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; 2CA045BE17117439006DEE8B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; - 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CA046611711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_iOS.h; sourceTree = ""; }; - 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_iOS.m; sourceTree = ""; }; - 2CA046651711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2CAB8687172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; + 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2CAB8689172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_iOS.h; sourceTree = ""; }; + 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_iOS.m; sourceTree = ""; }; + 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "ExampleApp-iOS/Default-568h@2x.png"; sourceTree = ""; }; 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 2CEB3EC11602563600548120 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 2CEB3EC31602563600548120 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 2CF988CD170E0BA500CA0CC7 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -57,10 +57,10 @@ 2CA045B617117439006DEE8B /* ExampleApp-iOS */ = { isa = PBXGroup; children = ( - 2CA0465F1711ACC2006DEE8B /* WebViewJavascriptBridge */, 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, + 2CAB8684172766B000BD9ED1 /* WebViewJavascriptBridge_iOS */, 2CA046211711A94E006DEE8B /* Supporting Files */, ); path = "ExampleApp-iOS"; @@ -77,22 +77,31 @@ name = "Supporting Files"; sourceTree = ""; }; - 2CA0465F1711ACC2006DEE8B /* WebViewJavascriptBridge */ = { + 2CAB8684172766B000BD9ED1 /* WebViewJavascriptBridge_iOS */ = { isa = PBXGroup; children = ( - 2CA046601711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt */, - 2CA046611711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.h */, - 2CA046621711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m */, - 2CA046651711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.h */, - 2CA046661711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m */, + 2CAB8685172766B000BD9ED1 /* WebViewJavascriptAbstract */, + 2CAB8689172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.h */, + 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */, ); - path = WebViewJavascriptBridge; - sourceTree = SOURCE_ROOT; + name = WebViewJavascriptBridge_iOS; + path = ../../WebViewJavascriptBridge_iOS; + sourceTree = ""; + }; + 2CAB8685172766B000BD9ED1 /* WebViewJavascriptAbstract */ = { + isa = PBXGroup; + children = ( + 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */, + 2CAB8687172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.h */, + 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */, + ); + path = WebViewJavascriptAbstract; + sourceTree = ""; }; 2CEB3EB01602563600548120 = { isa = PBXGroup; children = ( - 2CF988CD170E0BA500CA0CC7 /* Default-568h@2x.png */, + 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */, 2CA045B617117439006DEE8B /* ExampleApp-iOS */, 2CEB3EBE1602563600548120 /* Frameworks */, 2CEB3EBC1602563600548120 /* Products */, @@ -168,10 +177,10 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2CF988CE170E0BA500CA0CC7 /* Default-568h@2x.png in Resources */, 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */, 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */, - 2CA046671711ACC2006DEE8B /* WebViewJavascriptBridge.js.txt in Resources */, + 2CAB868B172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */, + 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -184,8 +193,8 @@ files = ( 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, - 2CA046681711ACC2006DEE8B /* WebViewJavascriptBridge_iOS.m in Sources */, - 2CA0466A1711ACC2006DEE8B /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2CAB868C172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2CAB868D172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Default-568h@2x.png b/Example Apps/ExampleApp-iOS/Default-568h@2x.png similarity index 100% rename from Default-568h@2x.png rename to Example Apps/ExampleApp-iOS/Default-568h@2x.png diff --git a/ExampleApp-iOS/ExampleApp-iOS-Info.plist b/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist similarity index 100% rename from ExampleApp-iOS/ExampleApp-iOS-Info.plist rename to Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist diff --git a/ExampleApp-iOS/ExampleApp-iOS-Prefix.pch b/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Prefix.pch similarity index 100% rename from ExampleApp-iOS/ExampleApp-iOS-Prefix.pch rename to Example Apps/ExampleApp-iOS/ExampleApp-iOS-Prefix.pch diff --git a/ExampleApp-iOS/ExampleAppDelegate.h b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h similarity index 100% rename from ExampleApp-iOS/ExampleAppDelegate.h rename to Example Apps/ExampleApp-iOS/ExampleAppDelegate.h diff --git a/ExampleApp-iOS/ExampleAppDelegate.m b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m similarity index 100% rename from ExampleApp-iOS/ExampleAppDelegate.m rename to Example Apps/ExampleApp-iOS/ExampleAppDelegate.m diff --git a/ExampleApp-iOS/en.lproj/InfoPlist.strings b/Example Apps/ExampleApp-iOS/en.lproj/InfoPlist.strings similarity index 100% rename from ExampleApp-iOS/en.lproj/InfoPlist.strings rename to Example Apps/ExampleApp-iOS/en.lproj/InfoPlist.strings diff --git a/ExampleApp-iOS/main.m b/Example Apps/ExampleApp-iOS/main.m similarity index 100% rename from ExampleApp-iOS/main.m rename to Example Apps/ExampleApp-iOS/main.m diff --git a/ExampleApp.html b/Example Apps/ExampleApp.html similarity index 100% rename from ExampleApp.html rename to Example Apps/ExampleApp.html diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt rename to WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridgeAbstract.h rename to WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridgeAbstract.m b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridgeAbstract.m rename to WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract b/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract new file mode 120000 index 00000000..2cb3269a --- /dev/null +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract @@ -0,0 +1 @@ +../WebViewJavascriptBridgeAbstract \ No newline at end of file diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.h rename to WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge_OSX.m rename to WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract b/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract new file mode 120000 index 00000000..2cb3269a --- /dev/null +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract @@ -0,0 +1 @@ +../WebViewJavascriptBridgeAbstract \ No newline at end of file diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge_iOS.h rename to WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m similarity index 100% rename from WebViewJavascriptBridge/WebViewJavascriptBridge_iOS.m rename to WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m From 0c529da77ad45f09a7d075ab55bec968da4334a3 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 23 Apr 2013 18:11:30 -0700 Subject: [PATCH 071/342] resolve compile-time warning --- .../WebViewJavascriptBridgeAbstract.h | 2 +- .../WebViewJavascriptBridgeAbstract.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h index 11864b6a..a5d3cd83 100644 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h @@ -12,7 +12,7 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @property (nonatomic, strong) NSMutableArray *startupMessageQueue; @property (nonatomic, strong) NSMutableDictionary *responseCallbacks; @property (nonatomic, strong) NSMutableDictionary *messageHandlers; -@property (atomic, assign) NSInteger uniqueId; +@property (atomic, assign) long uniqueId; @property (nonatomic, copy) WVJBHandler messageHandler; + (void)enableLogging; diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m index 830a5581..7e2408a2 100755 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m @@ -51,7 +51,7 @@ - (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)re NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; if (responseCallback) { - NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%d", ++self.uniqueId]; + NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++self.uniqueId]; self.responseCallbacks[callbackId] = [responseCallback copy]; message[@"callbackId"] = callbackId; } From 8486e00c173627efdc38d9db53718146e09a4cb4 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 23 Apr 2013 18:26:42 -0700 Subject: [PATCH 072/342] update README instructions to deal with both iOS and OSX --- README.md | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index edccdc15..562b9152 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ WebViewJavascriptBridge ======================= -An iOS bridge for sending messages to and from javascript in a UIWebView. +An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews. -If you like WebViewJavascriptBridge you should also check out [WebViewProxy](https://github.com/marcuswestin/WebViewProxy). +If you like WebViewJavascriptBridge you may also want to check out [WebViewProxy](https://github.com/marcuswestin/WebViewProxy). In the Wild ----------- -WebViewJavascriptBridge is used by a range of companies and projects. This list was just started and is still very incomplete. +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. - [Yardsale](https://www.getyardsale.com/) - [EverTrue](http://www.evertrue.com/) @@ -17,27 +17,26 @@ WebViewJavascriptBridge is used by a range of companies and projects. This list - Flutterby Labs - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) -Are you using WebViewJavascript at your company? Add it and send us a pull request! +Setup & Examples (iOS & OSX) +---------------------------- -Setup & Examples (iOS) ----------------- - -Just open the Xcode project and hit run to see ExampleApp run. +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: -1) Drag the `WebViewJavascriptBridge` folder into your project. +1) Drag the `WebViewJavascriptBridge_iOS` or `WebViewJavascriptBridge_OSX` folder into your project. - In the dialog that appears, uncheck "Copy items into destination group's folder" and select "Create groups for any folders" - - Delete OSX files. - + 2) Import the header file: + // for iOS: #import "WebViewJavascriptBridge_iOS.h" + // for OSX: + #import "WebViewJavascriptBridge_OSX.h" -3) Instantiate a UIWebView and a WebViewJavascriptBridge: +3) Instantiate WebViewJavascriptBridge with a UIWebView (iOS) or WebView (OSX): - UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"Received message from javascript: %@", data); responseCallback(@"Right back atcha"); @@ -72,14 +71,14 @@ API Reference ### ObjC API -##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView*)webview handler:(WVJBHandler)handler]` -##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]` +##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview handler:(WVJBHandler)handler]` +##### `[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]` -Create a javascript bridge for the given UIWebView. +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 [UIWebView's lifecycle events](http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html). +Optionally, pass in `webViewDelegate:(UIWebViewDelegate*)webViewDelegate` if you need to respond to the [web view's lifecycle events](http://developer.apple.com/library/ios/documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html). Example: @@ -186,7 +185,7 @@ Example: iOS4 support (with JSONKit) --------------------------- -*Note*: iOS4 support has not yet been tested in v2. +*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](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. From 6a5cb6530175a24fda759461825c62646d2f6ca2 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 23 Apr 2013 18:28:28 -0700 Subject: [PATCH 073/342] Add @oakho to list of contributors, and reassign copyright of entire library to include both Marcus Westin and Antoine Lagadec. --- Example Apps/ExampleApp-OSX/AppDelegate.h | 8 -------- Example Apps/ExampleApp-OSX/AppDelegate.m | 8 -------- Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist | 2 +- Example Apps/ExampleApp-OSX/main.m | 8 -------- Example Apps/ExampleApp-iOS/main.m | 8 -------- LICENSE | 2 +- README.md | 4 ++-- WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h | 8 -------- WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m | 8 -------- WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h | 8 -------- WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m | 8 -------- 11 files changed, 4 insertions(+), 68 deletions(-) diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.h b/Example Apps/ExampleApp-OSX/AppDelegate.h index 96bb190a..ddbd75fd 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.h +++ b/Example Apps/ExampleApp-OSX/AppDelegate.h @@ -1,11 +1,3 @@ -// -// AppDelegate.h -// ExampleApp-OSX -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Antoine Lagadec. All rights reserved. -// - #import #import "WebViewJavascriptBridge_OSX.h" diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m index ed31863b..4db9997b 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -1,11 +1,3 @@ -// -// AppDelegate.m -// ExampleApp-OSX -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Antoine Lagadec. All rights reserved. -// - #import "AppDelegate.h" @implementation AppDelegate diff --git a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist index 5a46a8d8..18703404 100644 --- a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist +++ b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist @@ -25,7 +25,7 @@ LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright - Copyright © 2013 Antoine Lagadec. All rights reserved. + Copyright © 2013 Marcus Westin, Antoine Lagadec. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass diff --git a/Example Apps/ExampleApp-OSX/main.m b/Example Apps/ExampleApp-OSX/main.m index ae7b871a..04d99dab 100644 --- a/Example Apps/ExampleApp-OSX/main.m +++ b/Example Apps/ExampleApp-OSX/main.m @@ -1,11 +1,3 @@ -// -// main.m -// ExampleApp-OSX -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Antoine Lagadec. All rights reserved. -// - #import int main(int argc, char *argv[]) diff --git a/Example Apps/ExampleApp-iOS/main.m b/Example Apps/ExampleApp-iOS/main.m index a724dc9c..5887dbf1 100644 --- a/Example Apps/ExampleApp-iOS/main.m +++ b/Example Apps/ExampleApp-iOS/main.m @@ -1,11 +1,3 @@ -// -// main.m -// ExampleApp -// -// Created by Marcus Westin on 9/13/12. -// Copyright (c) 2012 Marcus Westin. All rights reserved. -// - #import #import "ExampleAppDelegate.h" diff --git a/LICENSE b/LICENSE index d9d6b12d..1e732703 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 Marcus Westin +Copyright (c) 2011-2013 Marcus Westin, Antoine Lagadec Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/README.md b/README.md index 562b9152..ef79353f 100644 --- a/README.md +++ b/README.md @@ -191,8 +191,8 @@ WebViewJavascriptBridge uses `NSJSONSerialization` by default. If you need iOS 4 Contributors ------------ - -- [@marcuswestin](https://github.com/marcuswestin) Marcus Westin +- [@marcuswestin](https://github.com/marcuswestin) Marcus Westin (Author) +- [@oakho](https://github.com/oakho) Antoine Lagadec (OS X version) - [@psineur](https://github.com/psineur) Stepan Generalov - [@sergiocampama](https://github.com/sergiocampama) Sergio Campamá - [@stringbean](https://github.com/stringbean) Michael Stringer diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h index 9a8b2f4f..c9943ffa 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h @@ -1,11 +1,3 @@ -// -// WebViewJavascriptBridge+OSX.h -// ExampleApp-OSX -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Antoine Lagadec. All rights reserved. -// - #import #import "WebViewJavascriptBridgeAbstract.h" diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index 02ee2ed2..efe5f8e2 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -1,11 +1,3 @@ -// -// WebViewJavascriptBridge+OSX.m -// ExampleApp-OSX -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Antoine Lagadec. All rights reserved. -// - #import "WebViewJavascriptBridge_OSX.h" @implementation WebViewJavascriptBridge diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h index 3371f49f..69fb7020 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h @@ -1,11 +1,3 @@ -// -// WebViewJavascriptBridge+iOS.h -// ExampleApp-iOS -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Marcus Westin. All rights reserved. -// - #import #import "WebViewJavascriptBridgeAbstract.h" diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index de493c85..c9c48d24 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -1,11 +1,3 @@ -// -// WebViewJavascriptBridge+iOS.m -// ExampleApp-iOS -// -// Created by Antoine Lagadec on 07/04/13. -// Copyright (c) 2013 Marcus Westin. All rights reserved. -// - #import "WebViewJavascriptBridge_iOS.h" @implementation WebViewJavascriptBridge From 89d96975a95aa18025e4fc0d218699da8f45346b Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 23 Apr 2013 18:28:58 -0700 Subject: [PATCH 074/342] v3.0.0 with OSX support --- Changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog b/Changelog index 7733b5ac..e5667d04 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +v3.0.0 ++ OSX Support + v2.1.2 + Copy handler and response blocks From 6276d0d54221b8005ef5deb800cc547a6eadebaa Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 14:02:35 -0400 Subject: [PATCH 075/342] add instancetype to class constructors --- WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h | 4 ++-- WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h index 69fb7020..4f606dcb 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h @@ -6,7 +6,7 @@ @property (nonatomic, strong) UIWebView *webView; @property (nonatomic, strong) id webViewDelegate; -+ (id)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; -+ (id)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; @end diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index c9c48d24..bba73560 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -4,11 +4,11 @@ @implementation WebViewJavascriptBridge #pragma mark UIWebViewDelegate -+ (id)bridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { ++ (instancetype)bridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; } -+ (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { ++ (instancetype)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; bridge.messageHandler = messageHandler; bridge.webView = webView; From b06988f14aa92911d9773ef66d53b9822b05f6da Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 14:12:39 -0400 Subject: [PATCH 076/342] fix retain cycle --- .../WebViewJavascriptBridgeAbstract.h | 4 ++-- .../WebViewJavascriptBridgeAbstract.m | 12 ++++++---- .../WebViewJavascriptBridge_iOS.h | 4 ++-- .../WebViewJavascriptBridge_iOS.m | 24 +++++++++++-------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h index a5d3cd83..a99690f4 100644 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h @@ -7,8 +7,8 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridgeAbstract : NSObject -@property (nonatomic, strong) id webView; -@property (nonatomic, strong) id webViewDelegate; +@property (nonatomic, weak) id webView; +@property (nonatomic, weak) id webViewDelegate; @property (nonatomic, strong) NSMutableArray *startupMessageQueue; @property (nonatomic, strong) NSMutableDictionary *responseCallbacks; @property (nonatomic, strong) NSMutableDictionary *messageHandlers; diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m index 7e2408a2..0734e6e7 100755 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m @@ -79,13 +79,14 @@ - (void)_dispatchMessage:(NSDictionary *)message { messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; + __strong typeof(self.webView) strongWebView = self.webView; if ([[NSThread currentThread] isMainThread]) { - [self.webView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) + [strongWebView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) withObject:[NSString stringWithFormat: @"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; } else { dispatch_sync(dispatch_get_main_queue(), ^{ - [self.webView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) + [strongWebView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) withObject:[NSString stringWithFormat: @"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; }); @@ -93,7 +94,8 @@ - (void)_dispatchMessage:(NSDictionary *)message { } - (void)_flushMessageQueue { - NSString *messageQueueString = [self.webView performSelector: + __strong typeof(self.webView) strongWebView = self.webView; + NSString *messageQueueString = [strongWebView performSelector: @selector(stringByEvaluatingJavaScriptFromString:) withObject:@"WebViewJavascriptBridge._fetchQueue();"]; NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator]; @@ -112,8 +114,8 @@ - (void)_flushMessageQueue { __block NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { - NSDictionary* message = @{ @"responseId":callbackId, @"responseData":responseData }; - [self _queueMessage:message]; + NSDictionary* msg = @{ @"responseId":callbackId, @"responseData":responseData }; + [self _queueMessage:msg]; }; } else { responseCallback = ^(id ignoreResponseData) { diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h index 69fb7020..22752949 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h @@ -3,8 +3,8 @@ @interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract -@property (nonatomic, strong) UIWebView *webView; -@property (nonatomic, strong) id webViewDelegate; +@property (nonatomic, weak) UIWebView *webView; +@property (nonatomic, weak) id webViewDelegate; + (id)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; + (id)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index c9c48d24..a0275c67 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -24,10 +24,10 @@ + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id Date: Thu, 6 Jun 2013 14:53:50 -0400 Subject: [PATCH 077/342] track number of resources left to load, fixing race condition --- .../WebViewJavascriptBridge_iOS.m | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index c9c48d24..739bb0ce 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -1,5 +1,11 @@ #import "WebViewJavascriptBridge_iOS.h" +@interface WebViewJavascriptBridge () + +@property (nonatomic, assign) NSUInteger numRequestsLoading; + +@end + @implementation WebViewJavascriptBridge #pragma mark UIWebViewDelegate @@ -9,7 +15,7 @@ + (id)bridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { } + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { - WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + WebViewJavascriptBridge* bridge = [[[self class] alloc] init]; bridge.messageHandler = messageHandler; bridge.webView = webView; bridge.webViewDelegate = webViewDelegate; @@ -18,13 +24,16 @@ + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id Date: Thu, 6 Jun 2013 15:00:18 -0400 Subject: [PATCH 078/342] add OS X support --- .../WebViewJavascriptBridge_OSX.m | 18 ++++++++++++++++-- .../WebViewJavascriptBridge_iOS.m | 5 ++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index efe5f8e2..8c0369b0 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -1,5 +1,11 @@ #import "WebViewJavascriptBridge_OSX.h" +@interface WebViewJavascriptBridge () + +@property (nonatomic, assign) NSUInteger numRequestsLoading; + +@end + @implementation WebViewJavascriptBridge + (id)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { @@ -17,7 +23,7 @@ + (id)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate ha bridge.webView.frameLoadDelegate = bridge; bridge.webView.resourceLoadDelegate = bridge; bridge.webView.policyDelegate = bridge; - + return bridge; } @@ -25,7 +31,9 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - if (![[self.webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + self.numRequestsLoading--; + + if (self.numRequestsLoading == 0 && ![[self.webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [self.webView stringByEvaluatingJavaScriptFromString:js]; @@ -45,6 +53,9 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame - (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { if (webView != self.webView) { return; } + + self.numRequestsLoading--; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { [self.webViewDelegate webView:self.webView didFailLoadWithError:error forFrame:frame]; } @@ -78,6 +89,9 @@ - (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { if (webView != self.webView) { return request; } + + self.numRequestsLoading++; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { return [self.webViewDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; } diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index 739bb0ce..0dbe4265 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -23,14 +23,13 @@ + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id Date: Thu, 6 Jun 2013 15:01:10 -0400 Subject: [PATCH 079/342] add OS X support --- WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h | 4 ++-- WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h index c9943ffa..af46430d 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h @@ -6,7 +6,7 @@ @property (nonatomic, strong) WebView *webView; @property (nonatomic, strong) id webViewDelegate; -+ (id)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; -+ (id)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; @end diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index efe5f8e2..9efed22c 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -2,11 +2,11 @@ @implementation WebViewJavascriptBridge -+ (id)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { ++ (instancetype)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; } -+ (id)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { ++ (instancetype)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; bridge.messageHandler = messageHandler; bridge.webView = webView; From 5ec6c29ca01c04cad7037365d596742367dd7e39 Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 15:06:41 -0400 Subject: [PATCH 080/342] add OS X support --- .../WebViewJavascriptBridge_OSX.h | 4 +-- .../WebViewJavascriptBridge_OSX.m | 33 +++++++++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h index c9943ffa..89a89ab4 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h @@ -3,8 +3,8 @@ @interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract -@property (nonatomic, strong) WebView *webView; -@property (nonatomic, strong) id webViewDelegate; +@property (nonatomic, weak) WebView *webView; +@property (nonatomic, weak) id webViewDelegate; + (id)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; + (id)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index efe5f8e2..b90ff37c 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -7,7 +7,7 @@ + (id)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { } + (id)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { - WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + WebViewJavascriptBridge* bridge = [[[self class] alloc] init]; bridge.messageHandler = messageHandler; bridge.webView = webView; bridge.webViewDelegate = webViewDelegate; @@ -25,10 +25,10 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - if (![[self.webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - [self.webView stringByEvaluatingJavaScriptFromString:js]; + [webView stringByEvaluatingJavaScriptFromString:js]; } if (self.startupMessageQueue) { @@ -38,15 +38,17 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame self.startupMessageQueue = nil; } - if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) { - [self.webViewDelegate webView:webView didFinishLoadForFrame:frame]; + __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) { + [strongDelegate webView:webView didFinishLoadForFrame:frame]; } } - (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { - [self.webViewDelegate webView:self.webView didFailLoadWithError:error forFrame:frame]; + __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { + [strongDelegate webView:strongDelegate didFailLoadWithError:error forFrame:frame]; } } @@ -54,6 +56,7 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary { if (webView != self.webView) { [listener use]; } NSURL *url = [request URL]; + __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { if ([[url host] isEqualToString:kQueueHasMessage]) { [self _flushMessageQueue]; @@ -61,9 +64,9 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); } [listener ignore]; - } else if ([self.webView resourceLoadDelegate] - && [self.webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { - [self.webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; + } else if ([webView resourceLoadDelegate] + && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { + [strongDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; } else { [listener use]; } @@ -71,15 +74,17 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary - (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { - [self.webViewDelegate webView:webView didCommitLoadForFrame:frame]; + __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { + [strongDelegate webView:webView didCommitLoadForFrame:frame]; } } - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { if (webView != self.webView) { return request; } - if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { - return [self.webViewDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; + __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { + return [strongDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; } return request; From 618fe2ed74c92d8480c5ef9857a7901f4fea104e Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 15:12:10 -0400 Subject: [PATCH 081/342] add weak fallback for iOS 4 --- .../WebViewJavascriptBridgeAbstract.h | 12 ++++++++++-- .../WebViewJavascriptBridge_OSX.h | 4 ++-- .../WebViewJavascriptBridge_iOS.h | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h index a99690f4..de80ba9d 100644 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h @@ -2,13 +2,21 @@ #define kCustomProtocolScheme @"wvjbscheme" #define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" +#if TARGET_OS_IPHONE && defined(__IPHONE_5_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0) + #define WEAK_FALLBACK weak +#elif TARGET_OS_MAC && defined(__MAC_10_7) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7) + #define WEAK_FALLBACK weak +#else + #define WEAK_FALLBACK unsafe_unretained +#endif + typedef void (^WVJBResponseCallback)(id responseData); typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridgeAbstract : NSObject -@property (nonatomic, weak) id webView; -@property (nonatomic, weak) id webViewDelegate; +@property (nonatomic, WEAK_FALLBACK) id webView; +@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; @property (nonatomic, strong) NSMutableArray *startupMessageQueue; @property (nonatomic, strong) NSMutableDictionary *responseCallbacks; @property (nonatomic, strong) NSMutableDictionary *messageHandlers; diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h index 89a89ab4..c55bff02 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h @@ -3,8 +3,8 @@ @interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract -@property (nonatomic, weak) WebView *webView; -@property (nonatomic, weak) id webViewDelegate; +@property (nonatomic, WEAK_FALLBACK) WebView *webView; +@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; + (id)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; + (id)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h index 22752949..f1b318a5 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h @@ -3,8 +3,8 @@ @interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract -@property (nonatomic, weak) UIWebView *webView; -@property (nonatomic, weak) id webViewDelegate; +@property (nonatomic, WEAK_FALLBACK) UIWebView *webView; +@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; + (id)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; + (id)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; From 20ce1b0bcff3caa6e71b024647121498b82517dc Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 15:17:27 -0400 Subject: [PATCH 082/342] nil out delegates on dealloc --- WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m | 7 +++++++ WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index b90ff37c..9259e48d 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -21,6 +21,13 @@ + (id)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate ha return bridge; } +- (void)dealloc; +{ + self.webView.frameLoadDelegate = nil; + self.webView.resourceLoadDelegate = nil; + self.webView.policyDelegate = nil; +} + - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame { if (webView != self.webView) { return; } diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index a0275c67..d05b670c 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -21,6 +21,11 @@ + (id)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id Date: Thu, 6 Jun 2013 12:35:56 -0700 Subject: [PATCH 083/342] Add @peyton to list of contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ef79353f..e9bf51d4 100644 --- a/README.md +++ b/README.md @@ -201,3 +201,4 @@ Contributors - [@pj4533](https://github.com/pj4533) PJ Gray - [@xzeror](https://github.com/xzeror) - [@kelp404](https://github.com/kelp404) +- [@peyton](https://github.com/peyton) Peyton Randolph From 818d49cfc3bece2feee2a9c652520ad3f499e91e Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 16:04:40 -0400 Subject: [PATCH 084/342] Add podspec --- WebViewJavascriptBridge.podspec | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 WebViewJavascriptBridge.podspec diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec new file mode 100644 index 00000000..79735999 --- /dev/null +++ b/WebViewJavascriptBridge.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'WebViewJavascriptBridge' + s.version = '4.0.0pre' + s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' + s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } + s.source = { :git => 'https://github.com/peyton/WebViewJavascriptBridge.git' } + s.ios.platform = :ios, '5.0' + s.osx.platform = :osx + s.ios.source_files = 'WebViewJavascriptBridge_iOS/*.{h,m}', 'WebViewJavascriptBridgeAbstract/*.{h,m}' + s.osx.source_files = 'WebViewJavascriptBridge_OSX/*.{h,m}', 'WebViewJavascriptBridgeAbstract/*.{h,m}' + s.resource = 'WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt' + s.ios.framework = 'UIKit' + s.osx.framework = 'WebKit' +end From 7f0ec42415e513ea679c467ceb2f41a952aeb0bb Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 16:12:11 -0400 Subject: [PATCH 085/342] fix bug --- WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m | 1 - 1 file changed, 1 deletion(-) diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m index fce01d8f..59311ffe 100644 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m @@ -38,7 +38,6 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { self.numRequestsLoading--; if (self.numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:js]; From 95afe41a2cfa5232e61f58dc6a1d932a2274a6e3 Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Thu, 6 Jun 2013 16:17:39 -0400 Subject: [PATCH 086/342] add requires_arc --- WebViewJavascriptBridge.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 79735999..3a2c63cd 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -5,6 +5,7 @@ Pod::Spec.new do |s| s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } + s.requires_arc = true s.source = { :git => 'https://github.com/peyton/WebViewJavascriptBridge.git' } s.ios.platform = :ios, '5.0' s.osx.platform = :osx From 4f58e829160543f2adca4e483acf99596e7b70ba Mon Sep 17 00:00:00 2001 From: Peyton Randolph Date: Fri, 7 Jun 2013 07:44:51 -0400 Subject: [PATCH 087/342] point podspec to the parent repo --- WebViewJavascriptBridge.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 3a2c63cd..76b49fbd 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } s.requires_arc = true - s.source = { :git => 'https://github.com/peyton/WebViewJavascriptBridge.git' } + s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git' } s.ios.platform = :ios, '5.0' s.osx.platform = :osx s.ios.source_files = 'WebViewJavascriptBridge_iOS/*.{h,m}', 'WebViewJavascriptBridgeAbstract/*.{h,m}' From 8f1aaf9b3743d37df178e503f708b9cae3892c0c Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Sat, 8 Jun 2013 01:12:38 -0700 Subject: [PATCH 088/342] Fix #41 - remove __block to avoid losing callbackId. See http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/Blocks/Articles/bxVariables.html "Types of variables" #3 and #4 - we want callbackId to be non-mutable, const --- .../WebViewJavascriptBridgeAbstract.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m index 0734e6e7..98218c31 100755 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m @@ -111,7 +111,7 @@ - (void)_flushMessageQueue { [self.responseCallbacks removeObjectForKey:responseId]; } else { WVJBResponseCallback responseCallback = NULL; - __block NSString* callbackId = message[@"callbackId"]; + NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { NSDictionary* msg = @{ @"responseId":callbackId, @"responseData":responseData }; From 2f1623a2642c08ef2b95c7e4f06cab94a924d73b Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Sat, 8 Jun 2013 01:18:57 -0700 Subject: [PATCH 089/342] v3.1.0 --- Changelog | 7 +++++++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index e5667d04..849cadb2 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,12 @@ +v3.1.0 ++ Dont inject the WVJB bridge until all requests have finished loading (61b853) ++ Add podspec file (818d49cfc) ++ Memory leaks fixed (b06988f1, 20ce1b0b) ++ New major contributor @peyton! + v3.0.0 + OSX Support ++ New major contributor @oakho! v2.1.2 + Copy handler and response blocks diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 76b49fbd..647d8328 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.0.0pre' + s.version = '3.1.0' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 9e6972834d0e6f937086827d6cb3cf963f55aff0 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Sat, 8 Jun 2013 19:54:47 -0700 Subject: [PATCH 090/342] Remove the current OS X based example app, to be replaced in the next commit by a strictly programmatically created app --- .../ExampleApp-OSX.xcodeproj/project.pbxproj | 334 -- Example Apps/ExampleApp-OSX/AppDelegate.h | 14 - Example Apps/ExampleApp-OSX/AppDelegate.m | 51 - .../ExampleApp-OSX/ExampleApp-OSX-Info.plist | 34 - .../ExampleApp-OSX/ExampleApp-OSX-Prefix.pch | 7 - .../ExampleApp-OSX/en.lproj/InfoPlist.strings | 2 - .../ExampleApp-OSX/en.lproj/MainMenu.xib | 3614 ----------------- Example Apps/ExampleApp-OSX/main.m | 6 - 8 files changed, 4062 deletions(-) delete mode 100644 Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj delete mode 100644 Example Apps/ExampleApp-OSX/AppDelegate.h delete mode 100644 Example Apps/ExampleApp-OSX/AppDelegate.m delete mode 100644 Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist delete mode 100644 Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch delete mode 100644 Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings delete mode 100644 Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib delete mode 100644 Example Apps/ExampleApp-OSX/main.m diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj deleted file mode 100644 index 5e5e13ab..00000000 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ /dev/null @@ -1,334 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 2CA045DA171178E5006DEE8B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA045D9171178E5006DEE8B /* Cocoa.framework */; }; - 2CA045E4171178E6006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045E2171178E6006DEE8B /* InfoPlist.strings */; }; - 2CA045E6171178E6006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045E5171178E6006DEE8B /* main.m */; }; - 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045EC171178E6006DEE8B /* AppDelegate.m */; }; - 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045EE171178E6006DEE8B /* MainMenu.xib */; }; - 2CA0460517117B56006DEE8B /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CA0460417117B56006DEE8B /* WebKit.framework */; }; - 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465D1711AC96006DEE8B /* ExampleApp.html */; }; - 2CAB8695172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */; }; - 2CAB8696172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */; }; - 2CAB8697172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 2CA045D5171178E5006DEE8B /* ExampleApp-OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 2CA045D9171178E5006DEE8B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - 2CA045DC171178E5006DEE8B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; - 2CA045DD171178E5006DEE8B /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - 2CA045DE171178E5006DEE8B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 2CA045E1171178E6006DEE8B /* ExampleApp-OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-OSX-Info.plist"; sourceTree = ""; }; - 2CA045E3171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 2CA045E5171178E6006DEE8B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 2CA045E7171178E6006DEE8B /* ExampleApp-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-OSX-Prefix.pch"; sourceTree = ""; }; - 2CA045EB171178E6006DEE8B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 2CA045EC171178E6006DEE8B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 2CA045EF171178E6006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - 2CA0460417117B56006DEE8B /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 2CA0465D1711AC96006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = ExampleApp.html; path = ../ExampleApp.html; sourceTree = ""; }; - 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CAB8691172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; - 2CAB8693172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; - 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 2CA045D2171178E5006DEE8B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2CA0460517117B56006DEE8B /* WebKit.framework in Frameworks */, - 2CA045DA171178E5006DEE8B /* Cocoa.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2CA045CA171178E5006DEE8B = { - isa = PBXGroup; - children = ( - 2CA0460417117B56006DEE8B /* WebKit.framework */, - 2CA045DF171178E5006DEE8B /* ExampleApp-OSX */, - 2CA045D8171178E5006DEE8B /* Frameworks */, - 2CA045D6171178E5006DEE8B /* Products */, - ); - sourceTree = ""; - }; - 2CA045D6171178E5006DEE8B /* Products */ = { - isa = PBXGroup; - children = ( - 2CA045D5171178E5006DEE8B /* ExampleApp-OSX.app */, - ); - name = Products; - sourceTree = ""; - }; - 2CA045D8171178E5006DEE8B /* Frameworks */ = { - isa = PBXGroup; - children = ( - 2CA045D9171178E5006DEE8B /* Cocoa.framework */, - 2CA045DB171178E5006DEE8B /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = ""; - }; - 2CA045DB171178E5006DEE8B /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 2CA045DC171178E5006DEE8B /* AppKit.framework */, - 2CA045DD171178E5006DEE8B /* CoreData.framework */, - 2CA045DE171178E5006DEE8B /* Foundation.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 2CA045DF171178E5006DEE8B /* ExampleApp-OSX */ = { - isa = PBXGroup; - children = ( - 2CA0465D1711AC96006DEE8B /* ExampleApp.html */, - 2CA045EB171178E6006DEE8B /* AppDelegate.h */, - 2CA045EC171178E6006DEE8B /* AppDelegate.m */, - 2CA045EE171178E6006DEE8B /* MainMenu.xib */, - 2CAB868E172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX */, - 2CA045E0171178E6006DEE8B /* Supporting Files */, - ); - path = "ExampleApp-OSX"; - sourceTree = ""; - }; - 2CA045E0171178E6006DEE8B /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 2CA045E1171178E6006DEE8B /* ExampleApp-OSX-Info.plist */, - 2CA045E2171178E6006DEE8B /* InfoPlist.strings */, - 2CA045E5171178E6006DEE8B /* main.m */, - 2CA045E7171178E6006DEE8B /* ExampleApp-OSX-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 2CAB868E172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX */ = { - isa = PBXGroup; - children = ( - 2CAB868F172766DF00BD9ED1 /* WebViewJavascriptAbstract */, - 2CAB8693172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.h */, - 2CAB8694172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m */, - ); - name = WebViewJavascriptBridge_OSX; - path = ../../WebViewJavascriptBridge_OSX; - sourceTree = ""; - }; - 2CAB868F172766DF00BD9ED1 /* WebViewJavascriptAbstract */ = { - isa = PBXGroup; - children = ( - 2CAB8690172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt */, - 2CAB8691172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.h */, - 2CAB8692172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m */, - ); - path = WebViewJavascriptAbstract; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 2CA045D4171178E5006DEE8B /* ExampleApp-OSX */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2CA045F3171178E6006DEE8B /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */; - buildPhases = ( - 2CA045D1171178E5006DEE8B /* Sources */, - 2CA045D2171178E5006DEE8B /* Frameworks */, - 2CA045D3171178E5006DEE8B /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "ExampleApp-OSX"; - productName = "ExampleApp-OSX"; - productReference = 2CA045D5171178E5006DEE8B /* ExampleApp-OSX.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 2CA045CC171178E5006DEE8B /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0450; - ORGANIZATIONNAME = "Antoine Lagadec"; - }; - buildConfigurationList = 2CA045CF171178E5006DEE8B /* Build configuration list for PBXProject "ExampleApp-OSX" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 2CA045CA171178E5006DEE8B; - productRefGroup = 2CA045D6171178E5006DEE8B /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 2CA045D4171178E5006DEE8B /* ExampleApp-OSX */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 2CA045D3171178E5006DEE8B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2CA045E4171178E6006DEE8B /* InfoPlist.strings in Resources */, - 2CA045F0171178E6006DEE8B /* MainMenu.xib in Resources */, - 2CA0465E1711AC96006DEE8B /* ExampleApp.html in Resources */, - 2CAB8695172766DF00BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 2CA045D1171178E5006DEE8B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2CA045E6171178E6006DEE8B /* main.m in Sources */, - 2CA045ED171178E6006DEE8B /* AppDelegate.m in Sources */, - 2CAB8696172766DF00BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */, - 2CAB8697172766DF00BD9ED1 /* WebViewJavascriptBridge_OSX.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 2CA045E2171178E6006DEE8B /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 2CA045E3171178E6006DEE8B /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 2CA045EE171178E6006DEE8B /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 2CA045EF171178E6006DEE8B /* en */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 2CA045F1171178E6006DEE8B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.7; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 2CA045F2171178E6006DEE8B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.7; - SDKROOT = macosx; - }; - name = Release; - }; - 2CA045F4171178E6006DEE8B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; - INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 2CA045F5171178E6006DEE8B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; - INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2CA045CF171178E5006DEE8B /* Build configuration list for PBXProject "ExampleApp-OSX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2CA045F1171178E6006DEE8B /* Debug */, - 2CA045F2171178E6006DEE8B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2CA045F3171178E6006DEE8B /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2CA045F4171178E6006DEE8B /* Debug */, - 2CA045F5171178E6006DEE8B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 2CA045CC171178E5006DEE8B /* Project object */; -} diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.h b/Example Apps/ExampleApp-OSX/AppDelegate.h deleted file mode 100644 index ddbd75fd..00000000 --- a/Example Apps/ExampleApp-OSX/AppDelegate.h +++ /dev/null @@ -1,14 +0,0 @@ -#import -#import "WebViewJavascriptBridge_OSX.h" - -@interface AppDelegate : NSObject - -@property (assign) IBOutlet NSWindow *window; -@property (weak) IBOutlet WebView *webView; - -- (IBAction)sendMessage:(id)sender; -- (IBAction)callHandler:(id)sender; - -@property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge; - -@end diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m deleted file mode 100644 index 4db9997b..00000000 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ /dev/null @@ -1,51 +0,0 @@ -#import "AppDelegate.h" - -@implementation AppDelegate - -@synthesize javascriptBridge = _bridge; - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - [WebViewJavascriptBridge enableLogging]; - - _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"ObjC received message from JS: %@", data); - responseCallback(@"Response for message from ObjC"); - }]; - - [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"testObjcCallback called: %@", data); - responseCallback(@"Response from testObjcCallback"); - }]; - - [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) { - NSLog(@"objc got response! %@", responseData); - }]; - - [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; - - [self loadExamplePage:self.webView]; - - [_bridge send:@"A string sent from ObjC after Webview has loaded."]; -} - -- (IBAction)sendMessage:(id)sender { - [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) { - NSLog(@"sendMessage got response: %@", response); - }]; -} - -- (IBAction)callHandler:(id)sender { - NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"]; - [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { - NSLog(@"testJavascriptHandler responded: %@", response); - }]; -} - -- (void)loadExamplePage:(WebView*)webView { - NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; - NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; - [[self.webView mainFrame] loadHTMLString:appHtml baseURL:nil]; -} - -@end diff --git a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist deleted file mode 100644 index 18703404..00000000 --- a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - example.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSMinimumSystemVersion - ${MACOSX_DEPLOYMENT_TARGET} - NSHumanReadableCopyright - Copyright © 2013 Marcus Westin, Antoine Lagadec. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch deleted file mode 100644 index 32daebd5..00000000 --- a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch +++ /dev/null @@ -1,7 +0,0 @@ -// -// Prefix header for all source files of the 'ExampleApp-OSX' target in the 'ExampleApp-OSX' project -// - -#ifdef __OBJC__ - #import -#endif diff --git a/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings b/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff..00000000 --- a/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib b/Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib deleted file mode 100644 index b4989b1d..00000000 --- a/Example Apps/ExampleApp-OSX/en.lproj/MainMenu.xib +++ /dev/null @@ -1,3614 +0,0 @@ - - - - 1070 - 11E53 - 2844 - 1138.47 - 569.00 - - 2844 - 1810 - - - IBNSLayoutConstraint - NSButton - NSButtonCell - NSCustomObject - NSMenu - NSMenuItem - NSView - NSWindowTemplate - WebView - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - - PluginDependencyRecalculationVersion - - - - - NSApplication - - - FirstResponder - - - NSApplication - - - AMainMenu - - - - ExampleApp-OSX - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - submenuAction: - - ExampleApp-OSX - - - - About ExampleApp-OSX - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Preferences… - , - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Services - - 1048576 - 2147483647 - - - submenuAction: - - Services - - _NSServicesMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Hide ExampleApp-OSX - h - 1048576 - 2147483647 - - - - - - Hide Others - h - 1572864 - 2147483647 - - - - - - Show All - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Quit ExampleApp-OSX - q - 1048576 - 2147483647 - - - - - _NSAppleMenu - - - - - File - - 1048576 - 2147483647 - - - submenuAction: - - File - - - - New - n - 1048576 - 2147483647 - - - - - - Open… - o - 1048576 - 2147483647 - - - - - - Open Recent - - 1048576 - 2147483647 - - - submenuAction: - - Open Recent - - - - Clear Menu - - 1048576 - 2147483647 - - - - - _NSRecentDocumentsMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Close - w - 1048576 - 2147483647 - - - - - - Save… - s - 1048576 - 2147483647 - - - - - - Revert to Saved - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Page Setup... - P - 1179648 - 2147483647 - - - - - - - Print… - p - 1048576 - 2147483647 - - - - - - - - - Edit - - 1048576 - 2147483647 - - - submenuAction: - - Edit - - - - Undo - z - 1048576 - 2147483647 - - - - - - Redo - Z - 1179648 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Cut - x - 1048576 - 2147483647 - - - - - - Copy - c - 1048576 - 2147483647 - - - - - - Paste - v - 1048576 - 2147483647 - - - - - - Paste and Match Style - V - 1572864 - 2147483647 - - - - - - Delete - - 1048576 - 2147483647 - - - - - - Select All - a - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Find - - 1048576 - 2147483647 - - - submenuAction: - - Find - - - - Find… - f - 1048576 - 2147483647 - - - 1 - - - - Find and Replace… - f - 1572864 - 2147483647 - - - 12 - - - - Find Next - g - 1048576 - 2147483647 - - - 2 - - - - Find Previous - G - 1179648 - 2147483647 - - - 3 - - - - Use Selection for Find - e - 1048576 - 2147483647 - - - 7 - - - - Jump to Selection - j - 1048576 - 2147483647 - - - - - - - - - Spelling and Grammar - - 1048576 - 2147483647 - - - submenuAction: - - Spelling and Grammar - - - - Show Spelling and Grammar - : - 1048576 - 2147483647 - - - - - - Check Document Now - ; - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Check Spelling While Typing - - 1048576 - 2147483647 - - - - - - Check Grammar With Spelling - - 1048576 - 2147483647 - - - - - - Correct Spelling Automatically - - 2147483647 - - - - - - - - - Substitutions - - 1048576 - 2147483647 - - - submenuAction: - - Substitutions - - - - Show Substitutions - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Smart Copy/Paste - f - 1048576 - 2147483647 - - - 1 - - - - Smart Quotes - g - 1048576 - 2147483647 - - - 2 - - - - Smart Dashes - - 2147483647 - - - - - - Smart Links - G - 1179648 - 2147483647 - - - 3 - - - - Text Replacement - - 2147483647 - - - - - - - - - Transformations - - 2147483647 - - - submenuAction: - - Transformations - - - - Make Upper Case - - 2147483647 - - - - - - Make Lower Case - - 2147483647 - - - - - - Capitalize - - 2147483647 - - - - - - - - - Speech - - 1048576 - 2147483647 - - - submenuAction: - - Speech - - - - Start Speaking - - 1048576 - 2147483647 - - - - - - Stop Speaking - - 1048576 - 2147483647 - - - - - - - - - - - - Format - - 2147483647 - - - submenuAction: - - Format - - - - Font - - 2147483647 - - - submenuAction: - - Font - - - - Show Fonts - t - 1048576 - 2147483647 - - - - - - Bold - b - 1048576 - 2147483647 - - - 2 - - - - Italic - i - 1048576 - 2147483647 - - - 1 - - - - Underline - u - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Bigger - + - 1048576 - 2147483647 - - - 3 - - - - Smaller - - - 1048576 - 2147483647 - - - 4 - - - - YES - YES - - - 2147483647 - - - - - - Kern - - 2147483647 - - - submenuAction: - - Kern - - - - Use Default - - 2147483647 - - - - - - Use None - - 2147483647 - - - - - - Tighten - - 2147483647 - - - - - - Loosen - - 2147483647 - - - - - - - - - Ligatures - - 2147483647 - - - submenuAction: - - Ligatures - - - - Use Default - - 2147483647 - - - - - - Use None - - 2147483647 - - - - - - Use All - - 2147483647 - - - - - - - - - Baseline - - 2147483647 - - - submenuAction: - - Baseline - - - - Use Default - - 2147483647 - - - - - - Superscript - - 2147483647 - - - - - - Subscript - - 2147483647 - - - - - - Raise - - 2147483647 - - - - - - Lower - - 2147483647 - - - - - - - - - YES - YES - - - 2147483647 - - - - - - Show Colors - C - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Copy Style - c - 1572864 - 2147483647 - - - - - - Paste Style - v - 1572864 - 2147483647 - - - - - _NSFontMenu - - - - - Text - - 2147483647 - - - submenuAction: - - Text - - - - Align Left - { - 1048576 - 2147483647 - - - - - - Center - | - 1048576 - 2147483647 - - - - - - Justify - - 2147483647 - - - - - - Align Right - } - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Writing Direction - - 2147483647 - - - submenuAction: - - Writing Direction - - - - YES - Paragraph - - 2147483647 - - - - - - CURlZmF1bHQ - - 2147483647 - - - - - - CUxlZnQgdG8gUmlnaHQ - - 2147483647 - - - - - - CVJpZ2h0IHRvIExlZnQ - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - YES - Selection - - 2147483647 - - - - - - CURlZmF1bHQ - - 2147483647 - - - - - - CUxlZnQgdG8gUmlnaHQ - - 2147483647 - - - - - - CVJpZ2h0IHRvIExlZnQ - - 2147483647 - - - - - - - - - YES - YES - - - 2147483647 - - - - - - Show Ruler - - 2147483647 - - - - - - Copy Ruler - c - 1310720 - 2147483647 - - - - - - Paste Ruler - v - 1310720 - 2147483647 - - - - - - - - - - - - View - - 1048576 - 2147483647 - - - submenuAction: - - View - - - - Show Toolbar - t - 1572864 - 2147483647 - - - - - - Customize Toolbar… - - 1048576 - 2147483647 - - - - - - - - - Window - - 1048576 - 2147483647 - - - submenuAction: - - Window - - - - Minimize - m - 1048576 - 2147483647 - - - - - - Zoom - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Bring All to Front - - 1048576 - 2147483647 - - - - - _NSWindowsMenu - - - - - Help - - 2147483647 - - - submenuAction: - - Help - - - - ExampleApp-OSX Help - ? - 1048576 - 2147483647 - - - - - _NSHelpMenu - - - - _NSMainMenu - - - 15 - 2 - {{335, 390}, {480, 360}} - 1954021376 - ExampleApp-OSX - NSWindow - - - - - 256 - - - - 256 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple URL pasteboard type - Apple Web Archive pasteboard type - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - WebURLsWithTitlesPboardType - public.png - public.url - public.url-name - - {{0, 37}, {480, 323}} - - - - _NS:9 - - - - - - - - - - - YES - YES - - - - 268 - {{20, 10}, {97, 19}} - - - - _NS:9 - YES - - -2080374784 - 134217728 - Send message - - LucidaGrande - 12 - 16 - - _NS:9 - - -2038153216 - 164 - - - 400 - 75 - - - - - 268 - {{125, 10}, {86, 19}} - - - _NS:9 - YES - - -2080374784 - 134217728 - Call Handler - - _NS:9 - - -2038153216 - 164 - - - 400 - 75 - - - - {480, 360} - - - - - {{0, 0}, {1280, 778}} - {10000000000000, 10000000000000} - YES - - - AppDelegate - - - NSFontManager - - - - 256 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple URL pasteboard type - Apple Web Archive pasteboard type - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - WebURLsWithTitlesPboardType - public.png - public.url - public.url-name - - {254, 200} - - - - _NS:9 - - - - YES - YES - - - - - - - terminate: - - - - 449 - - - - orderFrontStandardAboutPanel: - - - - 142 - - - - delegate - - - - 495 - - - - performMiniaturize: - - - - 37 - - - - arrangeInFront: - - - - 39 - - - - print: - - - - 86 - - - - runPageLayout: - - - - 87 - - - - clearRecentDocuments: - - - - 127 - - - - performClose: - - - - 193 - - - - toggleContinuousSpellChecking: - - - - 222 - - - - undo: - - - - 223 - - - - copy: - - - - 224 - - - - checkSpelling: - - - - 225 - - - - paste: - - - - 226 - - - - stopSpeaking: - - - - 227 - - - - cut: - - - - 228 - - - - showGuessPanel: - - - - 230 - - - - redo: - - - - 231 - - - - selectAll: - - - - 232 - - - - startSpeaking: - - - - 233 - - - - delete: - - - - 235 - - - - performZoom: - - - - 240 - - - - performFindPanelAction: - - - - 241 - - - - centerSelectionInVisibleArea: - - - - 245 - - - - toggleGrammarChecking: - - - - 347 - - - - toggleSmartInsertDelete: - - - - 355 - - - - toggleAutomaticQuoteSubstitution: - - - - 356 - - - - toggleAutomaticLinkDetection: - - - - 357 - - - - saveDocument: - - - - 362 - - - - revertDocumentToSaved: - - - - 364 - - - - runToolbarCustomizationPalette: - - - - 365 - - - - toggleToolbarShown: - - - - 366 - - - - hide: - - - - 367 - - - - hideOtherApplications: - - - - 368 - - - - unhideAllApplications: - - - - 370 - - - - newDocument: - - - - 373 - - - - openDocument: - - - - 374 - - - - raiseBaseline: - - - - 426 - - - - lowerBaseline: - - - - 427 - - - - copyFont: - - - - 428 - - - - subscript: - - - - 429 - - - - superscript: - - - - 430 - - - - tightenKerning: - - - - 431 - - - - underline: - - - - 432 - - - - orderFrontColorPanel: - - - - 433 - - - - useAllLigatures: - - - - 434 - - - - loosenKerning: - - - - 435 - - - - pasteFont: - - - - 436 - - - - unscript: - - - - 437 - - - - useStandardKerning: - - - - 438 - - - - useStandardLigatures: - - - - 439 - - - - turnOffLigatures: - - - - 440 - - - - turnOffKerning: - - - - 441 - - - - toggleAutomaticSpellingCorrection: - - - - 456 - - - - orderFrontSubstitutionsPanel: - - - - 458 - - - - toggleAutomaticDashSubstitution: - - - - 461 - - - - toggleAutomaticTextReplacement: - - - - 463 - - - - uppercaseWord: - - - - 464 - - - - capitalizeWord: - - - - 467 - - - - lowercaseWord: - - - - 468 - - - - pasteAsPlainText: - - - - 486 - - - - performFindPanelAction: - - - - 487 - - - - performFindPanelAction: - - - - 488 - - - - performFindPanelAction: - - - - 489 - - - - showHelp: - - - - 493 - - - - alignCenter: - - - - 518 - - - - pasteRuler: - - - - 519 - - - - toggleRuler: - - - - 520 - - - - alignRight: - - - - 521 - - - - copyRuler: - - - - 522 - - - - alignJustified: - - - - 523 - - - - alignLeft: - - - - 524 - - - - makeBaseWritingDirectionNatural: - - - - 525 - - - - makeBaseWritingDirectionLeftToRight: - - - - 526 - - - - makeBaseWritingDirectionRightToLeft: - - - - 527 - - - - makeTextWritingDirectionNatural: - - - - 528 - - - - makeTextWritingDirectionLeftToRight: - - - - 529 - - - - makeTextWritingDirectionRightToLeft: - - - - 530 - - - - performFindPanelAction: - - - - 535 - - - - addFontTrait: - - - - 421 - - - - addFontTrait: - - - - 422 - - - - modifyFont: - - - - 423 - - - - orderFrontFontPanel: - - - - 424 - - - - modifyFont: - - - - 425 - - - - window - - - - 532 - - - - webView - - - - 543 - - - - sendMessage: - - - - 555 - - - - callHandler: - - - - 556 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 29 - - - - - - - - - - - - - - 19 - - - - - - - - 56 - - - - - - - - 217 - - - - - - - - 83 - - - - - - - - 81 - - - - - - - - - - - - - - - - - 75 - - - - - 78 - - - - - 72 - - - - - 82 - - - - - 124 - - - - - - - - 77 - - - - - 73 - - - - - 79 - - - - - 112 - - - - - 74 - - - - - 125 - - - - - - - - 126 - - - - - 205 - - - - - - - - - - - - - - - - - - - - - - 202 - - - - - 198 - - - - - 207 - - - - - 214 - - - - - 199 - - - - - 203 - - - - - 197 - - - - - 206 - - - - - 215 - - - - - 218 - - - - - - - - 216 - - - - - - - - 200 - - - - - - - - - - - - - 219 - - - - - 201 - - - - - 204 - - - - - 220 - - - - - - - - - - - - - 213 - - - - - 210 - - - - - 221 - - - - - 208 - - - - - 209 - - - - - 57 - - - - - - - - - - - - - - - - - - 58 - - - - - 134 - - - - - 150 - - - - - 136 - - - - - 144 - - - - - 129 - - - - - 143 - - - - - 236 - - - - - 131 - - - - - - - - 149 - - - - - 145 - - - - - 130 - - - - - 24 - - - - - - - - - - - 92 - - - - - 5 - - - - - 239 - - - - - 23 - - - - - 295 - - - - - - - - 296 - - - - - - - - - 297 - - - - - 298 - - - - - 211 - - - - - - - - 212 - - - - - - - - - 195 - - - - - 196 - - - - - 346 - - - - - 348 - - - - - - - - 349 - - - - - - - - - - - - - - 350 - - - - - 351 - - - - - 354 - - - - - 371 - - - - - - - - 372 - - - - - 11 - 0 - - 11 - 1 - - 0.0 - - 1000 - - 6 - 24 - 2 - - - - 5 - 0 - - 6 - 1 - - 8 - - 1000 - - 6 - 24 - 3 - - - - 3 - 0 - - 4 - 1 - - 8 - - 1000 - - 6 - 24 - 3 - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - - 8 - 29 - 3 - - - - 6 - 0 - - 6 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - 3 - 0 - - 3 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - 5 - 0 - - 5 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - - - - - - 375 - - - - - - - - 376 - - - - - - - - - 377 - - - - - - - - 388 - - - - - - - - - - - - - - - - - - - - - - - 389 - - - - - 390 - - - - - 391 - - - - - 392 - - - - - 393 - - - - - 394 - - - - - 395 - - - - - 396 - - - - - 397 - - - - - - - - 398 - - - - - - - - 399 - - - - - - - - 400 - - - - - 401 - - - - - 402 - - - - - 403 - - - - - 404 - - - - - 405 - - - - - - - - - - - - 406 - - - - - 407 - - - - - 408 - - - - - 409 - - - - - 410 - - - - - 411 - - - - - - - - - - 412 - - - - - 413 - - - - - 414 - - - - - 415 - - - - - - - - - - - 416 - - - - - 417 - - - - - 418 - - - - - 419 - - - - - 420 - - - - - 450 - - - - - - - - 451 - - - - - - - - - - 452 - - - - - 453 - - - - - 454 - - - - - 457 - - - - - 459 - - - - - 460 - - - - - 462 - - - - - 465 - - - - - 466 - - - - - 485 - - - - - 490 - - - - - - - - 491 - - - - - - - - 492 - - - - - 494 - - - - - 496 - - - - - - - - 497 - - - - - - - - - - - - - - - - - 498 - - - - - 499 - - - - - 500 - - - - - 501 - - - - - 502 - - - - - 503 - - - - - - - - 504 - - - - - 505 - - - - - 506 - - - - - 507 - - - - - 508 - - - - - - - - - - - - - - - - 509 - - - - - 510 - - - - - 511 - - - - - 512 - - - - - 513 - - - - - 514 - - - - - 515 - - - - - 516 - - - - - 517 - - - - - 534 - - - - - 536 - - - - - 8 - 0 - - 0 - 1 - - 323 - - 1000 - - 3 - 9 - 1 - - - - - - 539 - - - - - 540 - - - - - 542 - - - - - 544 - - - - - 545 - - - - - - - - 546 - - - - - 550 - - - - - 551 - - - - - - - - 552 - - - - - 554 - - - - - 557 - - - - - 558 - - - - - 559 - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{380, 496}, {480, 360}} - - - - - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - - com.apple.WebKitIBPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - - - 559 - - - - - AppDelegate - NSObject - - id - id - - - - callHandler: - id - - - sendMessage: - id - - - - WebView - NSWindow - - - - webView - WebView - - - window - NSWindow - - - - IBProjectSource - ./Classes/AppDelegate.h - - - - NSLayoutConstraint - NSObject - - IBProjectSource - ./Classes/NSLayoutConstraint.h - - - - - 0 - IBCocoaFramework - YES - 3 - - {11, 11} - {10, 3} - - YES - - diff --git a/Example Apps/ExampleApp-OSX/main.m b/Example Apps/ExampleApp-OSX/main.m deleted file mode 100644 index 04d99dab..00000000 --- a/Example Apps/ExampleApp-OSX/main.m +++ /dev/null @@ -1,6 +0,0 @@ -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **)argv); -} From b85f3ff273be12aec831808be7c681206493ea78 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Sat, 8 Jun 2013 19:58:03 -0700 Subject: [PATCH 091/342] Create an OS X example app that creates everything in code --- .../ExampleApp-OSX.xcodeproj/project.pbxproj | 340 ++++++++++++++++++ Example Apps/ExampleApp-OSX/AppDelegate.h | 15 + Example Apps/ExampleApp-OSX/AppDelegate.m | 87 +++++ .../ExampleApp-OSX/ExampleApp-OSX-Info.plist | 34 ++ .../ExampleApp-OSX/ExampleApp-OSX-Prefix.pch | 7 + Example Apps/ExampleApp-OSX/ExampleApp.html | 66 ++++ .../ExampleApp-OSX/en.lproj/Credits.rtf | 29 ++ .../ExampleApp-OSX/en.lproj/InfoPlist.strings | 2 + Example Apps/ExampleApp-OSX/main.m | 14 + 9 files changed, 594 insertions(+) create mode 100644 Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj create mode 100644 Example Apps/ExampleApp-OSX/AppDelegate.h create mode 100644 Example Apps/ExampleApp-OSX/AppDelegate.m create mode 100644 Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist create mode 100644 Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch create mode 100644 Example Apps/ExampleApp-OSX/ExampleApp.html create mode 100644 Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf create mode 100644 Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings create mode 100644 Example Apps/ExampleApp-OSX/main.m diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj new file mode 100644 index 00000000..248a1e84 --- /dev/null +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -0,0 +1,340 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A2417641106004C7401 /* Cocoa.framework */; }; + 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A2D17641106004C7401 /* InfoPlist.strings */; }; + 2C136A3117641106004C7401 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3017641106004C7401 /* main.m */; }; + 2C136A3517641106004C7401 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A3317641106004C7401 /* Credits.rtf */; }; + 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; }; + 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; }; + 2C136A4E176421B9004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A4D176421B9004C7401 /* ExampleApp.html */; }; + 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */; }; + 2C136A5717642680004C7401 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */; }; + 2C136A5817642680004C7401 /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2C136A2117641106004C7401 /* ExampleApp-OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2C136A2417641106004C7401 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 2C136A2717641106004C7401 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 2C136A2817641106004C7401 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 2C136A2917641106004C7401 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-OSX-Info.plist"; sourceTree = ""; }; + 2C136A2E17641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 2C136A3017641106004C7401 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-OSX-Prefix.pch"; sourceTree = ""; }; + 2C136A3417641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + 2C136A3617641106004C7401 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 2C136A3717641106004C7401 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 2C136A4117641236004C7401 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 2C136A4D176421B9004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; + 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2C136A5217642680004C7401 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; + 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; + 2C136A5417642680004C7401 /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; + 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2C136A1E17641106004C7401 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */, + 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2C136A1817641106004C7401 = { + isa = PBXGroup; + children = ( + 2C136A4117641236004C7401 /* WebKit.framework */, + 2C136A2A17641106004C7401 /* ExampleApp-OSX */, + 2C136A2317641106004C7401 /* Frameworks */, + 2C136A2217641106004C7401 /* Products */, + ); + sourceTree = ""; + }; + 2C136A2217641106004C7401 /* Products */ = { + isa = PBXGroup; + children = ( + 2C136A2117641106004C7401 /* ExampleApp-OSX.app */, + ); + name = Products; + sourceTree = ""; + }; + 2C136A2317641106004C7401 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2C136A2417641106004C7401 /* Cocoa.framework */, + 2C136A2617641106004C7401 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2C136A2617641106004C7401 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 2C136A2717641106004C7401 /* AppKit.framework */, + 2C136A2817641106004C7401 /* CoreData.framework */, + 2C136A2917641106004C7401 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 2C136A2A17641106004C7401 /* ExampleApp-OSX */ = { + isa = PBXGroup; + children = ( + 2C136A3617641106004C7401 /* AppDelegate.h */, + 2C136A3717641106004C7401 /* AppDelegate.m */, + 2C136A4D176421B9004C7401 /* ExampleApp.html */, + 2C136A4F17642680004C7401 /* WebViewJavascriptBridge_OSX */, + 2C136A2B17641106004C7401 /* Supporting Files */, + ); + path = "ExampleApp-OSX"; + sourceTree = ""; + }; + 2C136A2B17641106004C7401 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */, + 2C136A2D17641106004C7401 /* InfoPlist.strings */, + 2C136A3017641106004C7401 /* main.m */, + 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */, + 2C136A3317641106004C7401 /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 2C136A4F17642680004C7401 /* WebViewJavascriptBridge_OSX */ = { + isa = PBXGroup; + children = ( + 2C136A5017642680004C7401 /* WebViewJavascriptAbstract */, + 2C136A5417642680004C7401 /* WebViewJavascriptBridge_OSX.h */, + 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */, + ); + name = WebViewJavascriptBridge_OSX; + path = ../../WebViewJavascriptBridge_OSX; + sourceTree = ""; + }; + 2C136A5017642680004C7401 /* WebViewJavascriptAbstract */ = { + isa = PBXGroup; + children = ( + 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */, + 2C136A5217642680004C7401 /* WebViewJavascriptBridgeAbstract.h */, + 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */, + ); + path = WebViewJavascriptAbstract; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2C136A2017641106004C7401 /* ExampleApp-OSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */; + buildPhases = ( + 2C136A1D17641106004C7401 /* Sources */, + 2C136A1E17641106004C7401 /* Frameworks */, + 2C136A1F17641106004C7401 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ExampleApp-OSX"; + productName = "ExampleApp-OSX"; + productReference = 2C136A2117641106004C7401 /* ExampleApp-OSX.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2C136A1917641106004C7401 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0460; + ORGANIZATIONNAME = "Marcus Westin"; + }; + buildConfigurationList = 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2C136A1817641106004C7401; + productRefGroup = 2C136A2217641106004C7401 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2C136A2017641106004C7401 /* ExampleApp-OSX */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2C136A1F17641106004C7401 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */, + 2C136A3517641106004C7401 /* Credits.rtf in Resources */, + 2C136A4E176421B9004C7401 /* ExampleApp.html in Resources */, + 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2C136A1D17641106004C7401 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C136A3117641106004C7401 /* main.m in Sources */, + 2C136A3817641106004C7401 /* AppDelegate.m in Sources */, + 2C136A5717642680004C7401 /* WebViewJavascriptBridgeAbstract.m in Sources */, + 2C136A5817642680004C7401 /* WebViewJavascriptBridge_OSX.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2C136A2D17641106004C7401 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 2C136A2E17641106004C7401 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 2C136A3317641106004C7401 /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 2C136A3417641106004C7401 /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2C136A3C17641106004C7401 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 2C136A3D17641106004C7401 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + SDKROOT = macosx; + }; + name = Release; + }; + 2C136A3F17641106004C7401 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; + INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 2C136A4017641106004C7401 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; + INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C136A3C17641106004C7401 /* Debug */, + 2C136A3D17641106004C7401 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2C136A3F17641106004C7401 /* Debug */, + 2C136A4017641106004C7401 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2C136A1917641106004C7401 /* Project object */; +} diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.h b/Example Apps/ExampleApp-OSX/AppDelegate.h new file mode 100644 index 00000000..6d91daf4 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// ExampleApp-OSX +// +// Created by Marcus Westin on 6/8/13. +// Copyright (c) 2013 Marcus Westin. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + +@property (assign) IBOutlet NSWindow *window; + +@end diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m new file mode 100644 index 00000000..03724e00 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -0,0 +1,87 @@ +// +// AppDelegate.m +// ExampleApp-OSX +// +// Created by Marcus Westin on 6/8/13. +// Copyright (c) 2013 Marcus Westin. All rights reserved. +// + +#import "AppDelegate.h" +#import +#import "WebViewJavascriptBridge_OSX.h" + +@implementation AppDelegate { + WebView* _webView; + WebViewJavascriptBridge* _bridge; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + [self _createViews]; + [self _createBridge]; + [self _createObjcButtons]; + [self _loadPage]; +} + +- (void)_createBridge { + _bridge = [WebViewJavascriptBridge bridgeForWebView:_webView handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"ObjC received message from JS: %@", data); + responseCallback(@"Response for message from ObjC"); + }]; + + [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"testObjcCallback called: %@", data); + responseCallback(@"Response from testObjcCallback"); + }]; + + [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) { + NSLog(@"objc got response! %@", responseData); + }]; + + [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; +} + +- (void)_createObjcButtons { + NSButton *messageButton = [[NSButton alloc] initWithFrame:NSMakeRect(5, 0, 120, 40)]; + [messageButton setTitle:@"Send message"]; + [messageButton setBezelStyle:NSRoundedBezelStyle]; + [messageButton setTarget:self]; + [messageButton setAction:@selector(_sendMessage)]; + [_webView addSubview:messageButton]; + + NSButton *callbackButton = [[NSButton alloc] initWithFrame:NSMakeRect(120, 0, 120, 40)]; + [callbackButton setTitle:@"Call handler"]; + [callbackButton setBezelStyle:NSRoundedBezelStyle]; + [callbackButton setTarget:self]; + [callbackButton setAction:@selector(_callHandler)]; + [_webView addSubview:callbackButton]; +} + +- (void)_sendMessage { + [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) { + NSLog(@"sendMessage got response: %@", response); + }]; +} + +- (void)_callHandler { + NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"]; + [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { + NSLog(@"testJavascriptHandler responded: %@", response); + }]; +} + +- (void)_createViews { + NSView* contentView = _window.contentView; + _webView = [[WebView alloc] initWithFrame:contentView.frame]; + [_webView setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; + [contentView addSubview:_webView]; +} + +- (void)_loadPage { + NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; + NSString* html = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; + [[_webView mainFrame] loadHTMLString:html baseURL:nil]; +} + + +@end diff --git a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist new file mode 100644 index 00000000..14097880 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + WebViewJavascriptBridge.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + Copyright © 2013 Marcus Westin. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch new file mode 100644 index 00000000..32daebd5 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'ExampleApp-OSX' target in the 'ExampleApp-OSX' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Example Apps/ExampleApp-OSX/ExampleApp.html b/Example Apps/ExampleApp-OSX/ExampleApp.html new file mode 100644 index 00000000..9272e3f3 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/ExampleApp.html @@ -0,0 +1,66 @@ + + + + +

WebViewJavascriptBridge Demo

+ +
+ diff --git a/Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf b/Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf new file mode 100644 index 00000000..46576ef2 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings b/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Example Apps/ExampleApp-OSX/main.m b/Example Apps/ExampleApp-OSX/main.m new file mode 100644 index 00000000..0999e46a --- /dev/null +++ b/Example Apps/ExampleApp-OSX/main.m @@ -0,0 +1,14 @@ +// +// main.m +// ExampleApp-OSX +// +// Created by Marcus Westin on 6/8/13. +// Copyright (c) 2013 Marcus Westin. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} From a21cdd4e17bd17068e525c16b0f269c4a063b20d Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Sat, 8 Jun 2013 20:00:16 -0700 Subject: [PATCH 092/342] Use the same ExampleApp.html file in the OSX example app as the iOS example app uses --- .../ExampleApp-OSX.xcodeproj/project.pbxproj | 8 +-- Example Apps/ExampleApp-OSX/ExampleApp.html | 66 ------------------- 2 files changed, 4 insertions(+), 70 deletions(-) delete mode 100644 Example Apps/ExampleApp-OSX/ExampleApp.html diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index 248a1e84..34b8c107 100644 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -13,10 +13,10 @@ 2C136A3517641106004C7401 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A3317641106004C7401 /* Credits.rtf */; }; 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; }; 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; }; - 2C136A4E176421B9004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A4D176421B9004C7401 /* ExampleApp.html */; }; 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */; }; 2C136A5717642680004C7401 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */; }; 2C136A5817642680004C7401 /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */; }; + 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -33,12 +33,12 @@ 2C136A3617641106004C7401 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 2C136A3717641106004C7401 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 2C136A4117641236004C7401 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 2C136A4D176421B9004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; 2C136A5217642680004C7401 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; 2C136A5417642680004C7401 /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; + 2C136A5917642704004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -96,7 +96,7 @@ children = ( 2C136A3617641106004C7401 /* AppDelegate.h */, 2C136A3717641106004C7401 /* AppDelegate.m */, - 2C136A4D176421B9004C7401 /* ExampleApp.html */, + 2C136A5917642704004C7401 /* ExampleApp.html */, 2C136A4F17642680004C7401 /* WebViewJavascriptBridge_OSX */, 2C136A2B17641106004C7401 /* Supporting Files */, ); @@ -189,8 +189,8 @@ files = ( 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */, 2C136A3517641106004C7401 /* Credits.rtf in Resources */, - 2C136A4E176421B9004C7401 /* ExampleApp.html in Resources */, 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */, + 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example Apps/ExampleApp-OSX/ExampleApp.html b/Example Apps/ExampleApp-OSX/ExampleApp.html deleted file mode 100644 index 9272e3f3..00000000 --- a/Example Apps/ExampleApp-OSX/ExampleApp.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -

WebViewJavascriptBridge Demo

- -
- From 668573f8e740775c08c0c41333289b6172d91a5e Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 14 Jun 2013 11:14:52 -0700 Subject: [PATCH 093/342] Remove numRequestsLoading from the OSX bridge. Since didFinishLoadForFrame fires when the entire document has loaded (rather than when any individual resource has loaded), numRequestsLoading is simply not required for OS X and causes problems --- .../WebViewJavascriptBridge_OSX.m | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m index b442802a..5a29a0a3 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m @@ -1,11 +1,5 @@ #import "WebViewJavascriptBridge_OSX.h" -@interface WebViewJavascriptBridge () - -@property (nonatomic, assign) NSUInteger numRequestsLoading; - -@end - @implementation WebViewJavascriptBridge + (instancetype)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { @@ -38,9 +32,7 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - self.numRequestsLoading--; - - if (self.numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:js]; @@ -62,8 +54,6 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame - (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { if (webView != self.webView) { return; } - self.numRequestsLoading--; - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { [strongDelegate webView:strongDelegate didFailLoadWithError:error forFrame:frame]; @@ -101,8 +91,6 @@ - (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { if (webView != self.webView) { return request; } - self.numRequestsLoading++; - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { return [strongDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; From baf4a06d0867d11a856be578b9d9f8c19b8e4203 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 14 Jun 2013 11:20:11 -0700 Subject: [PATCH 094/342] Import WebKit in conditional OSX macro of WebViewJavascriptBridgeAbstract to avoid compiler warnings about stringByEvaluatingJavaScriptFromString: selector being undefined --- .../WebViewJavascriptBridgeAbstract.h | 1 + WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h index de80ba9d..30301c57 100644 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h +++ b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h @@ -6,6 +6,7 @@ #define WEAK_FALLBACK weak #elif TARGET_OS_MAC && defined(__MAC_10_7) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7) #define WEAK_FALLBACK weak + #import #else #define WEAK_FALLBACK unsafe_unretained #endif diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h index d674fa20..41e5305e 100644 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h @@ -1,4 +1,3 @@ -#import #import "WebViewJavascriptBridgeAbstract.h" @interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract From 57ee322a4c5310eadd28b28f4d8522cd54123301 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 14 Jun 2013 13:16:26 -0700 Subject: [PATCH 095/342] Simplify setup and file organization by doing away with the Abstract/iOS/OSX seperation. Instead, we manage the iOS/OSX platform specific part using macros --- .../ExampleApp-OSX.xcodeproj/project.pbxproj | 42 +- Example Apps/ExampleApp-OSX/AppDelegate.m | 2 +- .../ExampleApp-iOS.xcodeproj/project.pbxproj | 52 +-- .../ExampleApp-iOS/ExampleAppDelegate.h | 2 +- README.md | 7 +- WebViewJavascriptBridge.podspec | 4 +- .../WebViewJavascriptBridge.h | 51 +++ .../WebViewJavascriptBridge.js.txt | 0 .../WebViewJavascriptBridge.m | 378 ++++++++++++++++++ .../WebViewJavascriptBridgeAbstract.h | 48 --- .../WebViewJavascriptBridgeAbstract.m | 171 -------- .../WebViewJavascriptAbstract | 1 - .../WebViewJavascriptBridge_OSX.h | 11 - .../WebViewJavascriptBridge_OSX.m | 102 ----- .../WebViewJavascriptAbstract | 1 - .../WebViewJavascriptBridge_iOS.h | 12 - .../WebViewJavascriptBridge_iOS.m | 99 ----- 17 files changed, 468 insertions(+), 515 deletions(-) create mode 100644 WebViewJavascriptBridge/WebViewJavascriptBridge.h rename {WebViewJavascriptBridgeAbstract => WebViewJavascriptBridge}/WebViewJavascriptBridge.js.txt (100%) create mode 100644 WebViewJavascriptBridge/WebViewJavascriptBridge.m delete mode 100644 WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h delete mode 100755 WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m delete mode 120000 WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract delete mode 100644 WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h delete mode 100644 WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m delete mode 120000 WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract delete mode 100644 WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h delete mode 100644 WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index 34b8c107..18313cd6 100644 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -13,10 +13,9 @@ 2C136A3517641106004C7401 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A3317641106004C7401 /* Credits.rtf */; }; 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; }; 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; }; - 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */; }; - 2C136A5717642680004C7401 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */; }; - 2C136A5817642680004C7401 /* WebViewJavascriptBridge_OSX.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */; }; 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; }; + 2C1562C5176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */; }; + 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -33,12 +32,10 @@ 2C136A3617641106004C7401 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 2C136A3717641106004C7401 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 2C136A4117641236004C7401 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2C136A5217642680004C7401 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; - 2C136A5417642680004C7401 /* WebViewJavascriptBridge_OSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_OSX.h; sourceTree = ""; }; - 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_OSX.m; sourceTree = ""; }; 2C136A5917642704004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; + 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; + 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -97,7 +94,7 @@ 2C136A3617641106004C7401 /* AppDelegate.h */, 2C136A3717641106004C7401 /* AppDelegate.m */, 2C136A5917642704004C7401 /* ExampleApp.html */, - 2C136A4F17642680004C7401 /* WebViewJavascriptBridge_OSX */, + 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */, 2C136A2B17641106004C7401 /* Supporting Files */, ); path = "ExampleApp-OSX"; @@ -115,25 +112,15 @@ name = "Supporting Files"; sourceTree = ""; }; - 2C136A4F17642680004C7401 /* WebViewJavascriptBridge_OSX */ = { + 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 2C136A5017642680004C7401 /* WebViewJavascriptAbstract */, - 2C136A5417642680004C7401 /* WebViewJavascriptBridge_OSX.h */, - 2C136A5517642680004C7401 /* WebViewJavascriptBridge_OSX.m */, + 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */, + 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */, + 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */, ); - name = WebViewJavascriptBridge_OSX; - path = ../../WebViewJavascriptBridge_OSX; - sourceTree = ""; - }; - 2C136A5017642680004C7401 /* WebViewJavascriptAbstract */ = { - isa = PBXGroup; - children = ( - 2C136A5117642680004C7401 /* WebViewJavascriptBridge.js.txt */, - 2C136A5217642680004C7401 /* WebViewJavascriptBridgeAbstract.h */, - 2C136A5317642680004C7401 /* WebViewJavascriptBridgeAbstract.m */, - ); - path = WebViewJavascriptAbstract; + name = WebViewJavascriptBridge; + path = ../../WebViewJavascriptBridge; sourceTree = ""; }; /* End PBXGroup section */ @@ -187,9 +174,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2C1562C5176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */, 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */, 2C136A3517641106004C7401 /* Credits.rtf in Resources */, - 2C136A5617642680004C7401 /* WebViewJavascriptBridge.js.txt in Resources */, 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -202,9 +189,8 @@ buildActionMask = 2147483647; files = ( 2C136A3117641106004C7401 /* main.m in Sources */, + 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */, 2C136A3817641106004C7401 /* AppDelegate.m in Sources */, - 2C136A5717642680004C7401 /* WebViewJavascriptBridgeAbstract.m in Sources */, - 2C136A5817642680004C7401 /* WebViewJavascriptBridge_OSX.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m index 03724e00..d4b230c6 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -8,7 +8,7 @@ #import "AppDelegate.h" #import -#import "WebViewJavascriptBridge_OSX.h" +#import "WebViewJavascriptBridge.h" @implementation AppDelegate { WebView* _webView; diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 6a694a05..b71010e5 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -7,13 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */; }; + 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; }; 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045B717117439006DEE8B /* InfoPlist.strings */; }; 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; }; 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; }; 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */; }; - 2CAB868B172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */; }; - 2CAB868C172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */; }; - 2CAB868D172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */; }; 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */; }; 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; }; 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EC11602563600548120 /* Foundation.framework */; }; @@ -21,6 +20,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; + 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; + 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; 2CA045B817117439006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ExampleApp-iOS-Info.plist"; sourceTree = ""; }; 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-iOS-Prefix.pch"; sourceTree = ""; }; @@ -28,11 +30,6 @@ 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; 2CA045BE17117439006DEE8B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; - 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; - 2CAB8687172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeAbstract.h; sourceTree = ""; }; - 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeAbstract.m; sourceTree = ""; }; - 2CAB8689172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_iOS.h; sourceTree = ""; }; - 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_iOS.m; sourceTree = ""; }; 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "ExampleApp-iOS/Default-568h@2x.png"; sourceTree = ""; }; 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; @@ -54,13 +51,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */ = { + isa = PBXGroup; + children = ( + 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */, + 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */, + 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */, + ); + name = WebViewJavascriptBridge; + path = ../../WebViewJavascriptBridge; + sourceTree = ""; + }; 2CA045B617117439006DEE8B /* ExampleApp-iOS */ = { isa = PBXGroup; children = ( 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, - 2CAB8684172766B000BD9ED1 /* WebViewJavascriptBridge_iOS */, + 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */, 2CA046211711A94E006DEE8B /* Supporting Files */, ); path = "ExampleApp-iOS"; @@ -77,27 +85,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 2CAB8684172766B000BD9ED1 /* WebViewJavascriptBridge_iOS */ = { - isa = PBXGroup; - children = ( - 2CAB8685172766B000BD9ED1 /* WebViewJavascriptAbstract */, - 2CAB8689172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.h */, - 2CAB868A172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m */, - ); - name = WebViewJavascriptBridge_iOS; - path = ../../WebViewJavascriptBridge_iOS; - sourceTree = ""; - }; - 2CAB8685172766B000BD9ED1 /* WebViewJavascriptAbstract */ = { - isa = PBXGroup; - children = ( - 2CAB8686172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt */, - 2CAB8687172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.h */, - 2CAB8688172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m */, - ); - path = WebViewJavascriptAbstract; - sourceTree = ""; - }; 2CEB3EB01602563600548120 = { isa = PBXGroup; children = ( @@ -177,9 +164,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */, 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */, 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */, - 2CAB868B172766B000BD9ED1 /* WebViewJavascriptBridge.js.txt in Resources */, 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -191,10 +178,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */, 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, - 2CAB868C172766B000BD9ED1 /* WebViewJavascriptBridgeAbstract.m in Sources */, - 2CAB868D172766B000BD9ED1 /* WebViewJavascriptBridge_iOS.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h index b85422c5..5fc2d78b 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h @@ -1,5 +1,5 @@ #import -#import "WebViewJavascriptBridge_iOS.h" +#import "WebViewJavascriptBridge.h" @interface ExampleAppDelegate : UIResponder diff --git a/README.md b/README.md index e9bf51d4..3a8cec56 100644 --- a/README.md +++ b/README.md @@ -24,16 +24,13 @@ Start with the Example Apps/ folder. Open either the iOS or OSX project and hit To use a WebViewJavascriptBridge in your own project: -1) Drag the `WebViewJavascriptBridge_iOS` or `WebViewJavascriptBridge_OSX` folder into your project. +1) 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" 2) Import the header file: - // for iOS: - #import "WebViewJavascriptBridge_iOS.h" - // for OSX: - #import "WebViewJavascriptBridge_OSX.h" + #import "WebViewJavascriptBridge.h" 3) Instantiate WebViewJavascriptBridge with a UIWebView (iOS) or WebView (OSX): diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 647d8328..2471c7fa 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git' } s.ios.platform = :ios, '5.0' s.osx.platform = :osx - s.ios.source_files = 'WebViewJavascriptBridge_iOS/*.{h,m}', 'WebViewJavascriptBridgeAbstract/*.{h,m}' - s.osx.source_files = 'WebViewJavascriptBridge_OSX/*.{h,m}', 'WebViewJavascriptBridgeAbstract/*.{h,m}' + s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}' + s.osx.source_files = 'WebViewJavascriptBridge/*.{h,m}' s.resource = 'WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt' s.ios.framework = 'UIKit' s.osx.framework = 'WebKit' diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h new file mode 100644 index 00000000..141cd848 --- /dev/null +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -0,0 +1,51 @@ +// +// WebViewJavascriptBridge.h +// ExampleApp-iOS +// +// Created by Marcus Westin on 6/14/13. +// Copyright (c) 2013 Marcus Westin. All rights reserved. +// + +#import + +#define kMessageSeparator @"__WVJB_MESSAGE_SEPERATOR__" +#define kCustomProtocolScheme @"wvjbscheme" +#define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" + +#if TARGET_OS_IPHONE && defined(__IPHONE_5_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0) + #define WVJB_WEAK_FALLBACK weak +#elif TARGET_OS_MAC && defined(__MAC_10_7) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7) + #define WVJB_WEAK_FALLBACK weak +#else + #define WVJB_WEAK_FALLBACK unsafe_unretained +#endif + +#if defined __MAC_OS_X_VERSION_MAX_ALLOWED + #import + #define WVJB_PLATFORM_OSX + #define WVJB_WEBVIEW_TYPE WebView + #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject +#elif defined __IPHONE_OS_VERSION_MAX_ALLOWED + #define WVJB_PLATFORM_IOS + #define WVJB_WEBVIEW_TYPE UIWebView + #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject +#endif + +typedef void (^WVJBResponseCallback)(id responseData); +typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); + +@interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_TYPE + ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; ++ (void)enableLogging; + +- (void)send:(id)message; +- (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; +- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; +- (void)callHandler:(NSString*)handlerName; +- (void)callHandler:(NSString*)handlerName data:(id)data; +- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; +- (void)reset; + +@end diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt similarity index 100% rename from WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt rename to WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m new file mode 100644 index 00000000..6d67b5d2 --- /dev/null +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -0,0 +1,378 @@ +// +// WebViewJavascriptBridge.m +// ExampleApp-iOS +// +// Created by Marcus Westin on 6/14/13. +// Copyright (c) 2013 Marcus Westin. All rights reserved. +// + +#import "WebViewJavascriptBridge.h" + +@implementation WebViewJavascriptBridge { + __weak WVJB_WEBVIEW_TYPE* _webView; + __weak id _webViewDelegate; + NSMutableArray* _startupMessageQueue; + NSMutableDictionary* _responseCallbacks; + NSMutableDictionary* _messageHandlers; + long _uniqueId; + WVJBHandler _messageHandler; + +#if defined WVJB_PLATFORM_IOS + NSUInteger _numRequestsLoading; +#endif + +} + +/* API + *****/ + +static bool logging = false; ++ (void)enableLogging { logging = true; } + ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler { + return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; +} + ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler { + WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler]; + [bridge reset]; + return bridge; +} + +- (void)send:(NSDictionary *)data { + [self send:data responseCallback:nil]; +} + +- (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback { + [self _sendData:data responseCallback:responseCallback handlerName:nil]; +} + +- (void)callHandler:(NSString *)handlerName { + [self callHandler:handlerName data:nil responseCallback:nil]; +} + +- (void)callHandler:(NSString *)handlerName data:(id)data { + [self callHandler:handlerName data:data responseCallback:nil]; +} + +- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { + [self _sendData:data responseCallback:responseCallback handlerName:handlerName]; +} + +- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { + _messageHandlers[handlerName] = [handler copy]; +} + +- (void)reset { + _startupMessageQueue = [NSMutableArray array]; + _responseCallbacks = [NSMutableDictionary dictionary]; + _uniqueId = 0; +} + +/* Platform agnostic internals + *****************************/ + +- (void)dealloc { + [self _platformSpecificDealloc]; + + _webView = nil; + _webViewDelegate = nil; + _startupMessageQueue = nil; + _responseCallbacks = nil; + _messageHandlers = nil; + _messageHandler = nil; +} + +- (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { + NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; + + if (responseCallback) { + NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; + _responseCallbacks[callbackId] = [responseCallback copy]; + message[@"callbackId"] = callbackId; + } + + if (handlerName) { + message[@"handlerName"] = handlerName; + } + [self _queueMessage:message]; +} + +- (void)_queueMessage:(NSDictionary *)message { + if (_startupMessageQueue) { + [_startupMessageQueue addObject:message]; + } else { + [self _dispatchMessage:message]; + } +} + +- (void)_dispatchMessage:(NSDictionary *)message { + NSString *messageJSON = [self _serializeMessage:message]; + [self _log:@"sending" json:messageJSON]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; + + NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; + if ([[NSThread currentThread] isMainThread]) { + [_webView stringByEvaluatingJavaScriptFromString:javascriptCommand]; + } else { + __strong WVJB_WEBVIEW_TYPE* strongWebView = _webView; + dispatch_sync(dispatch_get_main_queue(), ^{ + [strongWebView stringByEvaluatingJavaScriptFromString:javascriptCommand]; + }); + } +} + +- (void)_flushMessageQueue { + NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"]; + + NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator]; + for (NSString *messageJSON in messages) { + [self _log:@"receivd" json:messageJSON]; + + NSDictionary* message = [self _deserializeMessageJSON:messageJSON]; + + NSString* responseId = message[@"responseId"]; + if (responseId) { + WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; + responseCallback(message[@"responseData"]); + [_responseCallbacks removeObjectForKey:responseId]; + } else { + WVJBResponseCallback responseCallback = NULL; + NSString* callbackId = message[@"callbackId"]; + if (callbackId) { + responseCallback = ^(id responseData) { + NSDictionary* msg = @{ @"responseId":callbackId, @"responseData":responseData }; + [self _queueMessage:msg]; + }; + } else { + responseCallback = ^(id ignoreResponseData) { + // Do nothing + }; + } + + WVJBHandler handler; + if (message[@"handlerName"]) { + handler = _messageHandlers[message[@"handlerName"]]; + if (!handler) { return NSLog(@"WVJB Warning: No handler for %@", message[@"handlerName"]); } + } else { + handler = _messageHandler; + } + + @try { + NSDictionary* data = message[@"data"]; + if (!data || ((id)data) == [NSNull null]) { data = [NSDictionary dictionary]; } + handler(data, responseCallback); + } + @catch (NSException *exception) { + NSLog(@"WebViewJavascriptBridge: WARNING: objc handler threw. %@ %@", message, exception); + } + } + } +} + +- (NSString *)_serializeMessage:(NSDictionary *)message { +#if defined _JSONKIT_H_ + return [message JSONString]; +#else + return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; +#endif +} + +- (NSDictionary *)_deserializeMessageJSON:(NSString *)messageJSON { +#if defined _JSONKIT_H_ + return [messageJSON objectFromJSONString]; +#else + return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; +#endif +} + +- (void)_log:(NSString *)action json:(NSString *)json { + if (!logging) { return; } + if (json.length > 500) { + NSLog(@"WVJB %@: %@", action, [[json substringToIndex:500] stringByAppendingString:@" [...]"]); + } else { + NSLog(@"WVJB %@: %@", action, json); + } +} + + + +/* Platform specific internals: OSX + **********************************/ +#if defined WVJB_PLATFORM_OSX + +- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler { + _messageHandler = messageHandler; + _webView = webView; + _webViewDelegate = webViewDelegate; + _messageHandlers = [NSMutableDictionary dictionary]; + + _webView.frameLoadDelegate = self; + _webView.resourceLoadDelegate = self; + _webView.policyDelegate = self; +} + +- (void) _platformSpecificDealloc { + _webView.frameLoadDelegate = nil; + _webView.resourceLoadDelegate = nil; + _webView.policyDelegate = nil; +} + +- (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame +{ + if (webView != _webView) { return; } + + if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + [webView stringByEvaluatingJavaScriptFromString:js]; + } + + if (_startupMessageQueue) { + for (id queuedMessage in _startupMessageQueue) { + [self _dispatchMessage:queuedMessage]; + } + _startupMessageQueue = nil; + } + + if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) { + [_webViewDelegate webView:webView didFinishLoadForFrame:frame]; + } +} + +- (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + if (webView != _webView) { return; } + + if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { + [_webViewDelegate webView:webView didFailLoadWithError:error forFrame:frame]; + } +} + +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener +{ + if (webView != _webView) { [listener use]; } + + NSURL *url = [request URL]; + if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { + if ([[url host] isEqualToString:kQueueHasMessage]) { + [self _flushMessageQueue]; + } else { + NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); + } + [listener ignore]; + } else if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { + [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; + } else { + [listener use]; + } +} + +- (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { + if (webView != _webView) { return; } + + if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { + [_webViewDelegate webView:webView didCommitLoadForFrame:frame]; + } +} + +- (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { + if (webView != _webView) { return request; } + + if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { + return [_webViewDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; + } + + return request; +} + + + +/* Platform specific internals: OSX + **********************************/ +#elif defined WVJB_PLATFORM_IOS + +- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { + _messageHandler = messageHandler; + _webView = webView; + _webViewDelegate = webViewDelegate; + _messageHandlers = [NSMutableDictionary dictionary]; + _webView.delegate = self; +} + +- (void) _platformSpecificDealloc { + _webView.delegate = nil; +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + if (webView != _webView) { return; } + + _numRequestsLoading--; + + if (_numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + [webView stringByEvaluatingJavaScriptFromString:js]; + } + + if (_startupMessageQueue) { + for (id queuedMessage in _startupMessageQueue) { + [self _dispatchMessage:queuedMessage]; + } + _startupMessageQueue = nil; + } + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { + [strongDelegate webViewDidFinishLoad:webView]; + } +} + +- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { + if (webView != _webView) { return; } + + _numRequestsLoading--; + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + [strongDelegate webView:webView didFailLoadWithError:error]; + } +} + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + if (webView != _webView) { return YES; } + NSURL *url = [request URL]; + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { + if ([[url host] isEqualToString:kQueueHasMessage]) { + [self _flushMessageQueue]; + } else { + NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); + } + return NO; + } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { + return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; + } else { + return YES; + } +} + +- (void)webViewDidStartLoad:(UIWebView *)webView { + if (webView != _webView) { return; } + + _numRequestsLoading++; + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { + [strongDelegate webViewDidStartLoad:webView]; + } +} + +#endif + +@end diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h deleted file mode 100644 index 30301c57..00000000 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.h +++ /dev/null @@ -1,48 +0,0 @@ -#define kMessageSeparator @"__WVJB_MESSAGE_SEPERATOR__" -#define kCustomProtocolScheme @"wvjbscheme" -#define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" - -#if TARGET_OS_IPHONE && defined(__IPHONE_5_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0) - #define WEAK_FALLBACK weak -#elif TARGET_OS_MAC && defined(__MAC_10_7) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7) - #define WEAK_FALLBACK weak - #import -#else - #define WEAK_FALLBACK unsafe_unretained -#endif - -typedef void (^WVJBResponseCallback)(id responseData); -typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); - -@interface WebViewJavascriptBridgeAbstract : NSObject - -@property (nonatomic, WEAK_FALLBACK) id webView; -@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; -@property (nonatomic, strong) NSMutableArray *startupMessageQueue; -@property (nonatomic, strong) NSMutableDictionary *responseCallbacks; -@property (nonatomic, strong) NSMutableDictionary *messageHandlers; -@property (atomic, assign) long uniqueId; -@property (nonatomic, copy) WVJBHandler messageHandler; - -+ (void)enableLogging; -- (void)send:(id)message; -- (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; -- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; -- (void)callHandler:(NSString*)handlerName; -- (void)callHandler:(NSString*)handlerName data:(id)data; -- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; -- (void)reset; - -@end - -@interface WebViewJavascriptBridgeAbstract (Protected) - -- (void)_flushMessageQueue; -- (void)_sendData:(NSDictionary*)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; -- (void)_queueMessage:(NSDictionary*)message; -- (void)_dispatchMessage:(NSDictionary*)message; -- (NSString*)_serializeMessage:(NSDictionary*)message; -- (NSDictionary*)_deserializeMessageJSON:(NSString*)messageJSON; -- (void)_log:(NSString*)type json:(NSString*)output; - -@end diff --git a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m b/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m deleted file mode 100755 index 98218c31..00000000 --- a/WebViewJavascriptBridgeAbstract/WebViewJavascriptBridgeAbstract.m +++ /dev/null @@ -1,171 +0,0 @@ -#import "WebViewJavascriptBridgeAbstract.h" - -#ifdef USE_JSONKIT - #import "JSONKit.h" -#endif - -@interface WebViewJavascriptBridgeAbstract () - -@end - -@implementation WebViewJavascriptBridgeAbstract - -static bool logging = false; -+ (void)enableLogging { logging = true; } - -- (void)send:(NSDictionary *)data { - [self send:data responseCallback:nil]; -} - -- (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback { - [self _sendData:data responseCallback:responseCallback handlerName:nil]; -} - -- (void)callHandler:(NSString *)handlerName { - [self callHandler:handlerName data:nil responseCallback:nil]; -} - -- (void)callHandler:(NSString *)handlerName data:(id)data { - [self callHandler:handlerName data:data responseCallback:nil]; -} - -- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [self _sendData:data responseCallback:responseCallback handlerName:handlerName]; -} - -- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - self.messageHandlers[handlerName] = [handler copy]; -} - -- (void)reset { - self.startupMessageQueue = [NSMutableArray array]; - self.responseCallbacks = [NSMutableDictionary dictionary]; - self.uniqueId = 0; -} - -@end - -@implementation WebViewJavascriptBridgeAbstract (Protected) - -- (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { - NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; - - if (responseCallback) { - NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++self.uniqueId]; - self.responseCallbacks[callbackId] = [responseCallback copy]; - message[@"callbackId"] = callbackId; - } - - if (handlerName) { - message[@"handlerName"] = handlerName; - } - [self _queueMessage:message]; -} - -- (void)_queueMessage:(NSDictionary *)message { - if (self.startupMessageQueue) { - [self.startupMessageQueue addObject:message]; - } else { - [self _dispatchMessage:message]; - } -} - -- (void)_dispatchMessage:(NSDictionary *)message { - NSString *messageJSON = [self _serializeMessage:message]; - [self _log:@"sending" json:messageJSON]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; - messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; - __strong typeof(self.webView) strongWebView = self.webView; - if ([[NSThread currentThread] isMainThread]) { - [strongWebView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) - withObject:[NSString stringWithFormat: - @"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; - } else { - dispatch_sync(dispatch_get_main_queue(), ^{ - [strongWebView performSelector:@selector(stringByEvaluatingJavaScriptFromString:) - withObject:[NSString stringWithFormat: - @"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]]; - }); - } -} - -- (void)_flushMessageQueue { - __strong typeof(self.webView) strongWebView = self.webView; - NSString *messageQueueString = [strongWebView performSelector: - @selector(stringByEvaluatingJavaScriptFromString:) withObject:@"WebViewJavascriptBridge._fetchQueue();"]; - - NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator]; - for (NSString *messageJSON in messages) { - [self _log:@"receivd" json:messageJSON]; - - NSDictionary* message = [self _deserializeMessageJSON:messageJSON]; - - NSString* responseId = message[@"responseId"]; - if (responseId) { - WVJBResponseCallback responseCallback = self.responseCallbacks[responseId]; - responseCallback(message[@"responseData"]); - [self.responseCallbacks removeObjectForKey:responseId]; - } else { - WVJBResponseCallback responseCallback = NULL; - NSString* callbackId = message[@"callbackId"]; - if (callbackId) { - responseCallback = ^(id responseData) { - NSDictionary* msg = @{ @"responseId":callbackId, @"responseData":responseData }; - [self _queueMessage:msg]; - }; - } else { - responseCallback = ^(id ignoreResponseData) { - // Do nothing - }; - } - - WVJBHandler handler; - if (message[@"handlerName"]) { - handler = self.messageHandlers[message[@"handlerName"]]; - if (!handler) { return NSLog(@"WVJB Warning: No handler for %@", message[@"handlerName"]); } - } else { - handler = self.messageHandler; - } - - @try { - NSDictionary* data = message[@"data"]; - if (!data || ((id)data) == [NSNull null]) { data = [NSDictionary dictionary]; } - handler(data, responseCallback); - } - @catch (NSException *exception) { - NSLog(@"WebViewJavascriptBridge: WARNING: objc handler threw. %@ %@", message, exception); - } - } - } -} - -- (NSString *)_serializeMessage:(NSDictionary *)message { -#ifdef USE_JSONKIT - return [message JSONString]; -#else - return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; -#endif -} - -- (NSDictionary *)_deserializeMessageJSON:(NSString *)messageJSON { -#ifdef USE_JSONKIT - return [messageJSON objectFromJSONString]; -#else - return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; -#endif -} - -- (void)_log:(NSString *)action json:(NSString *)json { - if (!logging) { return; } - if (json.length > 500) { - NSLog(@"WVJB %@: %@", action, [[json substringToIndex:500] stringByAppendingString:@" [...]"]); - } else { - NSLog(@"WVJB %@: %@", action, json); - } -} - -@end diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract b/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract deleted file mode 120000 index 2cb3269a..00000000 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptAbstract +++ /dev/null @@ -1 +0,0 @@ -../WebViewJavascriptBridgeAbstract \ No newline at end of file diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h deleted file mode 100644 index 41e5305e..00000000 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "WebViewJavascriptBridgeAbstract.h" - -@interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract - -@property (nonatomic, WEAK_FALLBACK) WebView *webView; -@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; - -+ (instancetype)bridgeForWebView:(WebView*)webView handler:(WVJBHandler)handler; -+ (instancetype)bridgeForWebView:(WebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)handler; - -@end diff --git a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m b/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m deleted file mode 100644 index 5a29a0a3..00000000 --- a/WebViewJavascriptBridge_OSX/WebViewJavascriptBridge_OSX.m +++ /dev/null @@ -1,102 +0,0 @@ -#import "WebViewJavascriptBridge_OSX.h" - -@implementation WebViewJavascriptBridge - -+ (instancetype)bridgeForWebView:(WebView *)webView handler:(WVJBHandler)handler { - return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; -} - -+ (instancetype)bridgeForWebView:(WebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { - WebViewJavascriptBridge* bridge = [[[self class] alloc] init]; - bridge.messageHandler = messageHandler; - bridge.webView = webView; - bridge.webViewDelegate = webViewDelegate; - bridge.messageHandlers = [NSMutableDictionary dictionary]; - [bridge reset]; - - bridge.webView.frameLoadDelegate = bridge; - bridge.webView.resourceLoadDelegate = bridge; - bridge.webView.policyDelegate = bridge; - - return bridge; -} - -- (void)dealloc; -{ - self.webView.frameLoadDelegate = nil; - self.webView.resourceLoadDelegate = nil; - self.webView.policyDelegate = nil; -} - -- (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame -{ - if (webView != self.webView) { return; } - - if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; - NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - [webView stringByEvaluatingJavaScriptFromString:js]; - } - - if (self.startupMessageQueue) { - for (id queuedMessage in self.startupMessageQueue) { - [self _dispatchMessage:queuedMessage]; - } - self.startupMessageQueue = nil; - } - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) { - [strongDelegate webView:webView didFinishLoadForFrame:frame]; - } -} - -- (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { - if (webView != self.webView) { return; } - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) { - [strongDelegate webView:strongDelegate didFailLoadWithError:error forFrame:frame]; - } -} - -- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener -{ - if (webView != self.webView) { [listener use]; } - NSURL *url = [request URL]; - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { - if ([[url host] isEqualToString:kQueueHasMessage]) { - [self _flushMessageQueue]; - } else { - NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); - } - [listener ignore]; - } else if ([webView resourceLoadDelegate] - && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { - [strongDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; - } else { - [listener use]; - } -} - -- (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { - if (webView != self.webView) { return; } - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { - [strongDelegate webView:webView didCommitLoadForFrame:frame]; - } -} - -- (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { - if (webView != self.webView) { return request; } - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { - return [strongDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; - } - - return request; -} - -@end diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract b/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract deleted file mode 120000 index 2cb3269a..00000000 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptAbstract +++ /dev/null @@ -1 +0,0 @@ -../WebViewJavascriptBridgeAbstract \ No newline at end of file diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h deleted file mode 100644 index b4dc7406..00000000 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.h +++ /dev/null @@ -1,12 +0,0 @@ -#import -#import "WebViewJavascriptBridgeAbstract.h" - -@interface WebViewJavascriptBridge : WebViewJavascriptBridgeAbstract - -@property (nonatomic, WEAK_FALLBACK) UIWebView *webView; -@property (nonatomic, WEAK_FALLBACK) id webViewDelegate; - -+ (instancetype)bridgeForWebView:(UIWebView*)webView handler:(WVJBHandler)handler; -+ (instancetype)bridgeForWebView:(UIWebView*)webView webViewDelegate:(id )webViewDelegate handler:(WVJBHandler)handler; - -@end diff --git a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m b/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m deleted file mode 100644 index 59311ffe..00000000 --- a/WebViewJavascriptBridge_iOS/WebViewJavascriptBridge_iOS.m +++ /dev/null @@ -1,99 +0,0 @@ -#import "WebViewJavascriptBridge_iOS.h" - -@interface WebViewJavascriptBridge () - -@property (nonatomic, assign) NSUInteger numRequestsLoading; - -@end - -@implementation WebViewJavascriptBridge - -#pragma mark UIWebViewDelegate - -+ (instancetype)bridgeForWebView:(UIWebView *)webView handler:(WVJBHandler)handler { - return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; -} - -+ (instancetype)bridgeForWebView:(UIWebView *)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { - WebViewJavascriptBridge* bridge = [[[self class] alloc] init]; - bridge.messageHandler = messageHandler; - bridge.webView = webView; - bridge.webViewDelegate = webViewDelegate; - bridge.messageHandlers = [NSMutableDictionary dictionary]; - [bridge reset]; - - [webView setDelegate:bridge]; - - return bridge; -} - -- (void)dealloc; -{ - self.webView.delegate = nil; -} - -- (void)webViewDidFinishLoad:(UIWebView *)webView { - if (webView != self.webView) { return; } - - self.numRequestsLoading--; - - if (self.numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; - NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - [webView stringByEvaluatingJavaScriptFromString:js]; - } - - if (self.startupMessageQueue) { - for (id queuedMessage in self.startupMessageQueue) { - [self _dispatchMessage:queuedMessage]; - } - self.startupMessageQueue = nil; - } - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { - [strongDelegate webViewDidFinishLoad:webView]; - } -} - -- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { - if (webView != self.webView) { return; } - - self.numRequestsLoading--; - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { - [strongDelegate webView:webView didFailLoadWithError:error]; - } -} - -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { - if (webView != self.webView) { return YES; } - NSURL *url = [request URL]; - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { - if ([[url host] isEqualToString:kQueueHasMessage]) { - [self _flushMessageQueue]; - } else { - NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); - } - return NO; - } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { - return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; - } else { - return YES; - } -} - -- (void)webViewDidStartLoad:(UIWebView *)webView { - if (webView != self.webView) { return; } - - self.numRequestsLoading++; - - __strong typeof(self.webViewDelegate) strongDelegate = self.webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { - [strongDelegate webViewDidStartLoad:webView]; - } -} - -@end From 254ea00267f8c1e03727885f4e1e0fd5f5c78be8 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 14 Jun 2013 13:17:58 -0700 Subject: [PATCH 096/342] If the webview is not our webview then we should not be making nagivation action decisions for it. --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 6d67b5d2..710331b4 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -256,7 +256,7 @@ - (void)webView:(WebView *)webView didFailLoadWithError:(NSError *)error forFram - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { - if (webView != _webView) { [listener use]; } + if (webView != _webView) { return; } NSURL *url = [request URL]; if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { From 090fc95e40a01ef392ef1d8e4ff346fce5579eed Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 14 Jun 2013 13:21:46 -0700 Subject: [PATCH 097/342] v4.0.0 --- Changelog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog b/Changelog index 849cadb2..374927ba 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +v4.0.0 ++ Consolidate platform-specific code into a single WebViewJavascriptBridge.m/h using macros (57ee322a4c5310eadd28b28f4d8522cd54123301) ++ Bugfix: Don't make navigation decisions for webviews we don't control (254ea00267f8c1e03727885f4e1e0fd5f5c78be8) + v3.1.0 + Dont inject the WVJB bridge until all requests have finished loading (61b853) + Add podspec file (818d49cfc) From 2b4a68c4188ae4499469f6a6fb194377b3fa010d Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 19 Jun 2013 14:17:56 -0700 Subject: [PATCH 098/342] Fix #45: Use __has_feature for arc weak support --- WebViewJavascriptBridge/WebViewJavascriptBridge.h | 8 -------- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 11 +++++++++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 141cd848..836d0c52 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -12,14 +12,6 @@ #define kCustomProtocolScheme @"wvjbscheme" #define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" -#if TARGET_OS_IPHONE && defined(__IPHONE_5_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0) - #define WVJB_WEAK_FALLBACK weak -#elif TARGET_OS_MAC && defined(__MAC_10_7) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7) - #define WVJB_WEAK_FALLBACK weak -#else - #define WVJB_WEAK_FALLBACK unsafe_unretained -#endif - #if defined __MAC_OS_X_VERSION_MAX_ALLOWED #import #define WVJB_PLATFORM_OSX diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 710331b4..bbd2c760 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -8,9 +8,16 @@ #import "WebViewJavascriptBridge.h" +#if __has_feature(objc_arc_weak) + #define WVJB_WEAK __weak +#else + #define WVJB_WEAK __unsafe_unretained +#endif + + @implementation WebViewJavascriptBridge { - __weak WVJB_WEBVIEW_TYPE* _webView; - __weak id _webViewDelegate; + WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView; + WVJB_WEAK id _webViewDelegate; NSMutableArray* _startupMessageQueue; NSMutableDictionary* _responseCallbacks; NSMutableDictionary* _messageHandlers; From c3503532f6ee364de5915e945f2d9e5d2671959f Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 19 Jun 2013 14:18:13 -0700 Subject: [PATCH 099/342] Add @wangjinhua to list of contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3a8cec56..6edd5797 100644 --- a/README.md +++ b/README.md @@ -199,3 +199,4 @@ Contributors - [@xzeror](https://github.com/xzeror) - [@kelp404](https://github.com/kelp404) - [@peyton](https://github.com/peyton) Peyton Randolph +- [@wangjinhua](https://github.com/wangjinhua) From 832e1ae2adc5483f6a92612436dbf1201c6e0a36 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 19 Jun 2013 14:18:32 -0700 Subject: [PATCH 100/342] Ensure that the response callback gets called, even if no handler has been defined --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index bbd2c760..58ef2e70 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -166,7 +166,10 @@ - (void)_flushMessageQueue { WVJBHandler handler; if (message[@"handlerName"]) { handler = _messageHandlers[message[@"handlerName"]]; - if (!handler) { return NSLog(@"WVJB Warning: No handler for %@", message[@"handlerName"]); } + if (!handler) { + NSLog(@"WVJB Warning: No handler for %@", message[@"handlerName"]); + return responseCallback(@{}); + } } else { handler = _messageHandler; } From d45feacdce95d8d00bfec0fb5c2252b8ade440ba Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 19 Jun 2013 14:19:38 -0700 Subject: [PATCH 101/342] v4.0.1 --- Changelog | 3 +++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 374927ba..632f803f 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +v4.0.1 ++ Fix detection of arc_weak support + v4.0.0 + Consolidate platform-specific code into a single WebViewJavascriptBridge.m/h using macros (57ee322a4c5310eadd28b28f4d8522cd54123301) + Bugfix: Don't make navigation decisions for webviews we don't control (254ea00267f8c1e03727885f4e1e0fd5f5c78be8) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 2471c7fa..ff4ac0bd 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '3.1.0' + s.version = '4.0.1' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 3ba0b84cce4d9c910f3c3c75c32ff6b3c0c28fe1 Mon Sep 17 00:00:00 2001 From: jacob berkman Date: Mon, 29 Jul 2013 21:47:10 -0700 Subject: [PATCH 102/342] use [NSNull null] instead of nil when using shorthand -callHandler: Fixes NSInvalidArgumentException: "attempt to insert nil object from objects[0]" --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 58ef2e70..8f2c4ab0 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -56,7 +56,7 @@ - (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)respons } - (void)callHandler:(NSString *)handlerName { - [self callHandler:handlerName data:nil responseCallback:nil]; + [self callHandler:handlerName data:[NSNull null] responseCallback:nil]; } - (void)callHandler:(NSString *)handlerName data:(id)data { From 9297f5c3db30945c31e1f38adea6dad4446666bd Mon Sep 17 00:00:00 2001 From: jacob berkman Date: Tue, 30 Jul 2013 09:59:23 -0700 Subject: [PATCH 103/342] encode message queue as JSON If JS included the separator as part of its data, the Obj-C side would interpret it incorrectly: WebViewJavascriptBridge.send('Including __WVJB_MESSAGE_SEPERATOR__ in my message is broken.'); Before: WVJB receivd: {"data":"Including WVJB receivd: in my message is broken."} After: WVJB receivd: {"data":"Including __WVJB_MESSAGE_SEPERATOR__ in my message is broken."} --- .../WebViewJavascriptBridge.h | 1 - .../WebViewJavascriptBridge.js.txt | 5 ++-- .../WebViewJavascriptBridge.m | 27 ++++++++++++------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 836d0c52..d2d0544b 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -8,7 +8,6 @@ #import -#define kMessageSeparator @"__WVJB_MESSAGE_SEPERATOR__" #define kCustomProtocolScheme @"wvjbscheme" #define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt index 7936c0e8..86303713 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt @@ -5,7 +5,6 @@ var receiveMessageQueue = [] var messageHandlers = {} - var MESSAGE_SEPARATOR = '__WVJB_MESSAGE_SEPERATOR__' var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme' var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__' @@ -46,12 +45,12 @@ responseCallbacks[callbackId] = responseCallback message['callbackId'] = callbackId } - sendMessageQueue.push(JSON.stringify(message)) + sendMessageQueue.push(message) messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE } function _fetchQueue() { - var messageQueueString = sendMessageQueue.join(MESSAGE_SEPARATOR) + var messageQueueString = JSON.stringify(sendMessageQueue) sendMessageQueue = [] return messageQueueString } diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 8f2c4ab0..1e4920a5 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -138,12 +138,18 @@ - (void)_dispatchMessage:(NSDictionary *)message { - (void)_flushMessageQueue { NSString *messageQueueString = [_webView stringByEvaluatingJavaScriptFromString:@"WebViewJavascriptBridge._fetchQueue();"]; - NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator]; - for (NSString *messageJSON in messages) { - [self _log:@"receivd" json:messageJSON]; - - NSDictionary* message = [self _deserializeMessageJSON:messageJSON]; - + id messages = [self _deserializeMessageJSON:messageQueueString]; + if (![messages isKindOfClass:[NSArray class]]) { + NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messages class], messages); + return; + } + for (NSDictionary *message in messages) { + if (![message isKindOfClass:[NSDictionary class]]) { + NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); + continue; + } + [self _log:@"receivd" json:message]; + NSString* responseId = message[@"responseId"]; if (responseId) { WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; @@ -202,10 +208,13 @@ - (NSDictionary *)_deserializeMessageJSON:(NSString *)messageJSON { #endif } -- (void)_log:(NSString *)action json:(NSString *)json { +- (void)_log:(NSString *)action json:(id)json { if (!logging) { return; } - if (json.length > 500) { - NSLog(@"WVJB %@: %@", action, [[json substringToIndex:500] stringByAppendingString:@" [...]"]); + if (![json isKindOfClass:[NSString class]]) { + json = [self _serializeMessage:json]; + } + if ([json length] > 500) { + NSLog(@"WVJB %@: %@ [...]", action, [json substringToIndex:500]); } else { NSLog(@"WVJB %@: %@", action, json); } From 1afebc96ccf53b5d0371256bfca828b021f1a56f Mon Sep 17 00:00:00 2001 From: Antoine Lagadec Date: Thu, 5 Sep 2013 14:05:47 +0200 Subject: [PATCH 104/342] Readd MainMenu.xib and change target down to 10.7 --- .../ExampleApp-OSX.xcodeproj/project.pbxproj | 6 + Example Apps/ExampleApp-OSX/MainMenu.xib | 3614 +++++++++++++++++ 2 files changed, 3620 insertions(+) create mode 100644 Example Apps/ExampleApp-OSX/MainMenu.xib diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index 18313cd6..1a78a146 100644 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; }; 2C1562C5176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */; }; 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */; }; + 2CF17F5317D8AACF006E828B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CF17F5217D8AACF006E828B /* MainMenu.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -36,6 +37,7 @@ 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 2C1562C3176BA9FF00B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; + 2CF17F5217D8AACF006E828B /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,6 +96,7 @@ 2C136A3617641106004C7401 /* AppDelegate.h */, 2C136A3717641106004C7401 /* AppDelegate.m */, 2C136A5917642704004C7401 /* ExampleApp.html */, + 2CF17F5217D8AACF006E828B /* MainMenu.xib */, 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */, 2C136A2B17641106004C7401 /* Supporting Files */, ); @@ -178,6 +181,7 @@ 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */, 2C136A3517641106004C7401 /* Credits.rtf in Resources */, 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */, + 2CF17F5317D8AACF006E828B /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -282,6 +286,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -294,6 +299,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; diff --git a/Example Apps/ExampleApp-OSX/MainMenu.xib b/Example Apps/ExampleApp-OSX/MainMenu.xib new file mode 100644 index 00000000..b7140d43 --- /dev/null +++ b/Example Apps/ExampleApp-OSX/MainMenu.xib @@ -0,0 +1,3614 @@ + + + + 1070 + 11E53 + 2844 + 1138.47 + 569.00 + + 2844 + 1810 + + + IBNSLayoutConstraint + NSButton + NSButtonCell + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + WebView + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + ExampleApp-OSX + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + ExampleApp-OSX + + + + About ExampleApp-OSX + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide ExampleApp-OSX + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit ExampleApp-OSX + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + + + Font + + 2147483647 + + + submenuAction: + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligatures + + 2147483647 + + + submenuAction: + + Ligatures + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + ExampleApp-OSX Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 360}} + 1954021376 + ExampleApp-OSX + NSWindow + + + + + 256 + + + + 256 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + {{0, 37}, {480, 323}} + + + + _NS:9 + + + + + + + + + + + YES + YES + + + + 268 + {{20, 10}, {97, 19}} + + + + _NS:9 + YES + + -2080374784 + 134217728 + Send message + + LucidaGrande + 12 + 16 + + _NS:9 + + -2038153216 + 164 + + + 400 + 75 + + + + + 268 + {{125, 10}, {86, 19}} + + + _NS:9 + YES + + -2080374784 + 134217728 + Call Handler + + _NS:9 + + -2038153216 + 164 + + + 400 + 75 + + + + {480, 360} + + + + + {{0, 0}, {1280, 778}} + {10000000000000, 10000000000000} + YES + + + AppDelegate + + + NSFontManager + + + + 256 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + {254, 200} + + + + _NS:9 + + + + YES + YES + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + window + + + + 532 + + + + webView + + + + 543 + + + + sendMessage: + + + + 555 + + + + callHandler: + + + + 556 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + + + + 372 + + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 494 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 536 + + + + + 8 + 0 + + 0 + 1 + + 323 + + 1000 + + 3 + 9 + 1 + + + + + + 539 + + + + + 540 + + + + + 542 + + + + + 544 + + + + + 545 + + + + + + + + 546 + + + + + 550 + + + + + 551 + + + + + + + + 552 + + + + + 554 + + + + + 557 + + + + + 558 + + + + + 559 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 559 + + + + + AppDelegate + NSObject + + id + id + + + + callHandler: + id + + + sendMessage: + id + + + + WebView + NSWindow + + + + webView + WebView + + + window + NSWindow + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + NSLayoutConstraint + NSObject + + IBProjectSource + ./Classes/NSLayoutConstraint.h + + + + + 0 + IBCocoaFramework + YES + 3 + + {11, 11} + {10, 3} + + YES + + From 1df2260564178ed46becd36420e334d78ff1e14a Mon Sep 17 00:00:00 2001 From: Antoine Lagadec Date: Thu, 5 Sep 2013 16:28:15 +0200 Subject: [PATCH 105/342] OSX - Empty Main Menu layout --- Example Apps/ExampleApp-OSX/MainMenu.xib | 6852 ++++++++++------------ 1 file changed, 3241 insertions(+), 3611 deletions(-) diff --git a/Example Apps/ExampleApp-OSX/MainMenu.xib b/Example Apps/ExampleApp-OSX/MainMenu.xib index b7140d43..7dd49232 100644 --- a/Example Apps/ExampleApp-OSX/MainMenu.xib +++ b/Example Apps/ExampleApp-OSX/MainMenu.xib @@ -1,3614 +1,3244 @@ - - 1070 - 11E53 - 2844 - 1138.47 - 569.00 - - 2844 - 1810 - - - IBNSLayoutConstraint - NSButton - NSButtonCell - NSCustomObject - NSMenu - NSMenuItem - NSView - NSWindowTemplate - WebView - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - - PluginDependencyRecalculationVersion - - - - - NSApplication - - - FirstResponder - - - NSApplication - - - AMainMenu - - - - ExampleApp-OSX - - 1048576 - 2147483647 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - submenuAction: - - ExampleApp-OSX - - - - About ExampleApp-OSX - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Preferences… - , - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Services - - 1048576 - 2147483647 - - - submenuAction: - - Services - - _NSServicesMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Hide ExampleApp-OSX - h - 1048576 - 2147483647 - - - - - - Hide Others - h - 1572864 - 2147483647 - - - - - - Show All - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Quit ExampleApp-OSX - q - 1048576 - 2147483647 - - - - - _NSAppleMenu - - - - - File - - 1048576 - 2147483647 - - - submenuAction: - - File - - - - New - n - 1048576 - 2147483647 - - - - - - Open… - o - 1048576 - 2147483647 - - - - - - Open Recent - - 1048576 - 2147483647 - - - submenuAction: - - Open Recent - - - - Clear Menu - - 1048576 - 2147483647 - - - - - _NSRecentDocumentsMenu - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Close - w - 1048576 - 2147483647 - - - - - - Save… - s - 1048576 - 2147483647 - - - - - - Revert to Saved - - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Page Setup... - P - 1179648 - 2147483647 - - - - - - - Print… - p - 1048576 - 2147483647 - - - - - - - - - Edit - - 1048576 - 2147483647 - - - submenuAction: - - Edit - - - - Undo - z - 1048576 - 2147483647 - - - - - - Redo - Z - 1179648 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Cut - x - 1048576 - 2147483647 - - - - - - Copy - c - 1048576 - 2147483647 - - - - - - Paste - v - 1048576 - 2147483647 - - - - - - Paste and Match Style - V - 1572864 - 2147483647 - - - - - - Delete - - 1048576 - 2147483647 - - - - - - Select All - a - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Find - - 1048576 - 2147483647 - - - submenuAction: - - Find - - - - Find… - f - 1048576 - 2147483647 - - - 1 - - - - Find and Replace… - f - 1572864 - 2147483647 - - - 12 - - - - Find Next - g - 1048576 - 2147483647 - - - 2 - - - - Find Previous - G - 1179648 - 2147483647 - - - 3 - - - - Use Selection for Find - e - 1048576 - 2147483647 - - - 7 - - - - Jump to Selection - j - 1048576 - 2147483647 - - - - - - - - - Spelling and Grammar - - 1048576 - 2147483647 - - - submenuAction: - - Spelling and Grammar - - - - Show Spelling and Grammar - : - 1048576 - 2147483647 - - - - - - Check Document Now - ; - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Check Spelling While Typing - - 1048576 - 2147483647 - - - - - - Check Grammar With Spelling - - 1048576 - 2147483647 - - - - - - Correct Spelling Automatically - - 2147483647 - - - - - - - - - Substitutions - - 1048576 - 2147483647 - - - submenuAction: - - Substitutions - - - - Show Substitutions - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Smart Copy/Paste - f - 1048576 - 2147483647 - - - 1 - - - - Smart Quotes - g - 1048576 - 2147483647 - - - 2 - - - - Smart Dashes - - 2147483647 - - - - - - Smart Links - G - 1179648 - 2147483647 - - - 3 - - - - Text Replacement - - 2147483647 - - - - - - - - - Transformations - - 2147483647 - - - submenuAction: - - Transformations - - - - Make Upper Case - - 2147483647 - - - - - - Make Lower Case - - 2147483647 - - - - - - Capitalize - - 2147483647 - - - - - - - - - Speech - - 1048576 - 2147483647 - - - submenuAction: - - Speech - - - - Start Speaking - - 1048576 - 2147483647 - - - - - - Stop Speaking - - 1048576 - 2147483647 - - - - - - - - - - - - Format - - 2147483647 - - - submenuAction: - - Format - - - - Font - - 2147483647 - - - submenuAction: - - Font - - - - Show Fonts - t - 1048576 - 2147483647 - - - - - - Bold - b - 1048576 - 2147483647 - - - 2 - - - - Italic - i - 1048576 - 2147483647 - - - 1 - - - - Underline - u - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Bigger - + - 1048576 - 2147483647 - - - 3 - - - - Smaller - - - 1048576 - 2147483647 - - - 4 - - - - YES - YES - - - 2147483647 - - - - - - Kern - - 2147483647 - - - submenuAction: - - Kern - - - - Use Default - - 2147483647 - - - - - - Use None - - 2147483647 - - - - - - Tighten - - 2147483647 - - - - - - Loosen - - 2147483647 - - - - - - - - - Ligatures - - 2147483647 - - - submenuAction: - - Ligatures - - - - Use Default - - 2147483647 - - - - - - Use None - - 2147483647 - - - - - - Use All - - 2147483647 - - - - - - - - - Baseline - - 2147483647 - - - submenuAction: - - Baseline - - - - Use Default - - 2147483647 - - - - - - Superscript - - 2147483647 - - - - - - Subscript - - 2147483647 - - - - - - Raise - - 2147483647 - - - - - - Lower - - 2147483647 - - - - - - - - - YES - YES - - - 2147483647 - - - - - - Show Colors - C - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Copy Style - c - 1572864 - 2147483647 - - - - - - Paste Style - v - 1572864 - 2147483647 - - - - - _NSFontMenu - - - - - Text - - 2147483647 - - - submenuAction: - - Text - - - - Align Left - { - 1048576 - 2147483647 - - - - - - Center - | - 1048576 - 2147483647 - - - - - - Justify - - 2147483647 - - - - - - Align Right - } - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Writing Direction - - 2147483647 - - - submenuAction: - - Writing Direction - - - - YES - Paragraph - - 2147483647 - - - - - - CURlZmF1bHQ - - 2147483647 - - - - - - CUxlZnQgdG8gUmlnaHQ - - 2147483647 - - - - - - CVJpZ2h0IHRvIExlZnQ - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - YES - Selection - - 2147483647 - - - - - - CURlZmF1bHQ - - 2147483647 - - - - - - CUxlZnQgdG8gUmlnaHQ - - 2147483647 - - - - - - CVJpZ2h0IHRvIExlZnQ - - 2147483647 - - - - - - - - - YES - YES - - - 2147483647 - - - - - - Show Ruler - - 2147483647 - - - - - - Copy Ruler - c - 1310720 - 2147483647 - - - - - - Paste Ruler - v - 1310720 - 2147483647 - - - - - - - - - - - - View - - 1048576 - 2147483647 - - - submenuAction: - - View - - - - Show Toolbar - t - 1572864 - 2147483647 - - - - - - Customize Toolbar… - - 1048576 - 2147483647 - - - - - - - - - Window - - 1048576 - 2147483647 - - - submenuAction: - - Window - - - - Minimize - m - 1048576 - 2147483647 - - - - - - Zoom - - 1048576 - 2147483647 - - - - - - YES - YES - - - 1048576 - 2147483647 - - - - - - Bring All to Front - - 1048576 - 2147483647 - - - - - _NSWindowsMenu - - - - - Help - - 2147483647 - - - submenuAction: - - Help - - - - ExampleApp-OSX Help - ? - 1048576 - 2147483647 - - - - - _NSHelpMenu - - - - _NSMainMenu - - - 15 - 2 - {{335, 390}, {480, 360}} - 1954021376 - ExampleApp-OSX - NSWindow - - - - - 256 - - - - 256 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple URL pasteboard type - Apple Web Archive pasteboard type - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - WebURLsWithTitlesPboardType - public.png - public.url - public.url-name - - {{0, 37}, {480, 323}} - - - - _NS:9 - - - - - - - - - - - YES - YES - - - - 268 - {{20, 10}, {97, 19}} - - - - _NS:9 - YES - - -2080374784 - 134217728 - Send message - - LucidaGrande - 12 - 16 - - _NS:9 - - -2038153216 - 164 - - - 400 - 75 - - - - - 268 - {{125, 10}, {86, 19}} - - - _NS:9 - YES - - -2080374784 - 134217728 - Call Handler - - _NS:9 - - -2038153216 - 164 - - - 400 - 75 - - - - {480, 360} - - - - - {{0, 0}, {1280, 778}} - {10000000000000, 10000000000000} - YES - - - AppDelegate - - - NSFontManager - - - - 256 - - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple URL pasteboard type - Apple Web Archive pasteboard type - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - WebURLsWithTitlesPboardType - public.png - public.url - public.url-name - - {254, 200} - - - - _NS:9 - - - - YES - YES - - - - - - - terminate: - - - - 449 - - - - orderFrontStandardAboutPanel: - - - - 142 - - - - delegate - - - - 495 - - - - performMiniaturize: - - - - 37 - - - - arrangeInFront: - - - - 39 - - - - print: - - - - 86 - - - - runPageLayout: - - - - 87 - - - - clearRecentDocuments: - - - - 127 - - - - performClose: - - - - 193 - - - - toggleContinuousSpellChecking: - - - - 222 - - - - undo: - - - - 223 - - - - copy: - - - - 224 - - - - checkSpelling: - - - - 225 - - - - paste: - - - - 226 - - - - stopSpeaking: - - - - 227 - - - - cut: - - - - 228 - - - - showGuessPanel: - - - - 230 - - - - redo: - - - - 231 - - - - selectAll: - - - - 232 - - - - startSpeaking: - - - - 233 - - - - delete: - - - - 235 - - - - performZoom: - - - - 240 - - - - performFindPanelAction: - - - - 241 - - - - centerSelectionInVisibleArea: - - - - 245 - - - - toggleGrammarChecking: - - - - 347 - - - - toggleSmartInsertDelete: - - - - 355 - - - - toggleAutomaticQuoteSubstitution: - - - - 356 - - - - toggleAutomaticLinkDetection: - - - - 357 - - - - saveDocument: - - - - 362 - - - - revertDocumentToSaved: - - - - 364 - - - - runToolbarCustomizationPalette: - - - - 365 - - - - toggleToolbarShown: - - - - 366 - - - - hide: - - - - 367 - - - - hideOtherApplications: - - - - 368 - - - - unhideAllApplications: - - - - 370 - - - - newDocument: - - - - 373 - - - - openDocument: - - - - 374 - - - - raiseBaseline: - - - - 426 - - - - lowerBaseline: - - - - 427 - - - - copyFont: - - - - 428 - - - - subscript: - - - - 429 - - - - superscript: - - - - 430 - - - - tightenKerning: - - - - 431 - - - - underline: - - - - 432 - - - - orderFrontColorPanel: - - - - 433 - - - - useAllLigatures: - - - - 434 - - - - loosenKerning: - - - - 435 - - - - pasteFont: - - - - 436 - - - - unscript: - - - - 437 - - - - useStandardKerning: - - - - 438 - - - - useStandardLigatures: - - - - 439 - - - - turnOffLigatures: - - - - 440 - - - - turnOffKerning: - - - - 441 - - - - toggleAutomaticSpellingCorrection: - - - - 456 - - - - orderFrontSubstitutionsPanel: - - - - 458 - - - - toggleAutomaticDashSubstitution: - - - - 461 - - - - toggleAutomaticTextReplacement: - - - - 463 - - - - uppercaseWord: - - - - 464 - - - - capitalizeWord: - - - - 467 - - - - lowercaseWord: - - - - 468 - - - - pasteAsPlainText: - - - - 486 - - - - performFindPanelAction: - - - - 487 - - - - performFindPanelAction: - - - - 488 - - - - performFindPanelAction: - - - - 489 - - - - showHelp: - - - - 493 - - - - alignCenter: - - - - 518 - - - - pasteRuler: - - - - 519 - - - - toggleRuler: - - - - 520 - - - - alignRight: - - - - 521 - - - - copyRuler: - - - - 522 - - - - alignJustified: - - - - 523 - - - - alignLeft: - - - - 524 - - - - makeBaseWritingDirectionNatural: - - - - 525 - - - - makeBaseWritingDirectionLeftToRight: - - - - 526 - - - - makeBaseWritingDirectionRightToLeft: - - - - 527 - - - - makeTextWritingDirectionNatural: - - - - 528 - - - - makeTextWritingDirectionLeftToRight: - - - - 529 - - - - makeTextWritingDirectionRightToLeft: - - - - 530 - - - - performFindPanelAction: - - - - 535 - - - - addFontTrait: - - - - 421 - - - - addFontTrait: - - - - 422 - - - - modifyFont: - - - - 423 - - - - orderFrontFontPanel: - - - - 424 - - - - modifyFont: - - - - 425 - - - - window - - - - 532 - - - - webView - - - - 543 - - - - sendMessage: - - - - 555 - - - - callHandler: - - - - 556 - - - - - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 29 - - - - - - - - - - - - - - 19 - - - - - - - - 56 - - - - - - - - 217 - - - - - - - - 83 - - - - - - - - 81 - - - - - - - - - - - - - - - - - 75 - - - - - 78 - - - - - 72 - - - - - 82 - - - - - 124 - - - - - - - - 77 - - - - - 73 - - - - - 79 - - - - - 112 - - - - - 74 - - - - - 125 - - - - - - - - 126 - - - - - 205 - - - - - - - - - - - - - - - - - - - - - - 202 - - - - - 198 - - - - - 207 - - - - - 214 - - - - - 199 - - - - - 203 - - - - - 197 - - - - - 206 - - - - - 215 - - - - - 218 - - - - - - - - 216 - - - - - - - - 200 - - - - - - - - - - - - - 219 - - - - - 201 - - - - - 204 - - - - - 220 - - - - - - - - - - - - - 213 - - - - - 210 - - - - - 221 - - - - - 208 - - - - - 209 - - - - - 57 - - - - - - - - - - - - - - - - - - 58 - - - - - 134 - - - - - 150 - - - - - 136 - - - - - 144 - - - - - 129 - - - - - 143 - - - - - 236 - - - - - 131 - - - - - - - - 149 - - - - - 145 - - - - - 130 - - - - - 24 - - - - - - - - - - - 92 - - - - - 5 - - - - - 239 - - - - - 23 - - - - - 295 - - - - - - - - 296 - - - - - - - - - 297 - - - - - 298 - - - - - 211 - - - - - - - - 212 - - - - - - - - - 195 - - - - - 196 - - - - - 346 - - - - - 348 - - - - - - - - 349 - - - - - - - - - - - - - - 350 - - - - - 351 - - - - - 354 - - - - - 371 - - - - - - - - 372 - - - - - 11 - 0 - - 11 - 1 - - 0.0 - - 1000 - - 6 - 24 - 2 - - - - 5 - 0 - - 6 - 1 - - 8 - - 1000 - - 6 - 24 - 3 - - - - 3 - 0 - - 4 - 1 - - 8 - - 1000 - - 6 - 24 - 3 - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - - 8 - 29 - 3 - - - - 6 - 0 - - 6 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - 3 - 0 - - 3 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - 5 - 0 - - 5 - 1 - - 0.0 - - 1000 - - 8 - 29 - 3 - - - - - - - - - 375 - - - - - - - - 376 - - - - - - - - - 377 - - - - - - - - 388 - - - - - - - - - - - - - - - - - - - - - - - 389 - - - - - 390 - - - - - 391 - - - - - 392 - - - - - 393 - - - - - 394 - - - - - 395 - - - - - 396 - - - - - 397 - - - - - - - - 398 - - - - - - - - 399 - - - - - - - - 400 - - - - - 401 - - - - - 402 - - - - - 403 - - - - - 404 - - - - - 405 - - - - - - - - - - - - 406 - - - - - 407 - - - - - 408 - - - - - 409 - - - - - 410 - - - - - 411 - - - - - - - - - - 412 - - - - - 413 - - - - - 414 - - - - - 415 - - - - - - - - - - - 416 - - - - - 417 - - - - - 418 - - - - - 419 - - - - - 420 - - - - - 450 - - - - - - - - 451 - - - - - - - - - - 452 - - - - - 453 - - - - - 454 - - - - - 457 - - - - - 459 - - - - - 460 - - - - - 462 - - - - - 465 - - - - - 466 - - - - - 485 - - - - - 490 - - - - - - - - 491 - - - - - - - - 492 - - - - - 494 - - - - - 496 - - - - - - - - 497 - - - - - - - - - - - - - - - - - 498 - - - - - 499 - - - - - 500 - - - - - 501 - - - - - 502 - - - - - 503 - - - - - - - - 504 - - - - - 505 - - - - - 506 - - - - - 507 - - - - - 508 - - - - - - - - - - - - - - - - 509 - - - - - 510 - - - - - 511 - - - - - 512 - - - - - 513 - - - - - 514 - - - - - 515 - - - - - 516 - - - - - 517 - - - - - 534 - - - - - 536 - - - - - 8 - 0 - - 0 - 1 - - 323 - - 1000 - - 3 - 9 - 1 - - - - - - 539 - - - - - 540 - - - - - 542 - - - - - 544 - - - - - 545 - - - - - - - - 546 - - - - - 550 - - - - - 551 - - - - - - - - 552 - - - - - 554 - - - - - 557 - - - - - 558 - - - - - 559 - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{380, 496}, {480, 360}} - - - - - - - - - - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - - com.apple.WebKitIBPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.WebKitIBPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - - - 559 - - - - - AppDelegate - NSObject - - id - id - - - - callHandler: - id - - - sendMessage: - id - - - - WebView - NSWindow - - - - webView - WebView - - - window - NSWindow - - - - IBProjectSource - ./Classes/AppDelegate.h - - - - NSLayoutConstraint - NSObject - - IBProjectSource - ./Classes/NSLayoutConstraint.h - - - - - 0 - IBCocoaFramework - YES - 3 - - {11, 11} - {10, 3} - - YES - + + 1070 + 11E53 + 2844 + 1138.47 + 569.00 + + 2844 + 1810 + + + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + WebView + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + ExampleApp-OSX + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + ExampleApp-OSX + + + + About ExampleApp-OSX + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide ExampleApp-OSX + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit ExampleApp-OSX + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + Format + + + + Font + + 2147483647 + + + submenuAction: + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligatures + + 2147483647 + + + submenuAction: + + Ligatures + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + ExampleApp-OSX Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 360}} + 1954021376 + ExampleApp-OSX + NSWindow + + + + + 256 + {480, 360} + + + + + {{0, 0}, {1280, 778}} + {10000000000000, 10000000000000} + YES + + + AppDelegate + + + NSFontManager + + + + 256 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + {254, 200} + + + _NS:9 + + + + + + + + + + + YES + YES + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + window + + + + 532 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 494 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 544 + + + + + 371 + + + + + + + + 372 + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 559 + + + + + AppDelegate + NSObject + + window + NSWindow + + + window + + window + NSWindow + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + + 0 + IBCocoaFramework + YES + 3 + + {11, 11} + {10, 3} + + YES + From 4859217465ebea744698eeaf1eb97a148f4121ea Mon Sep 17 00:00:00 2001 From: Miles Matthias Date: Fri, 13 Sep 2013 21:29:17 -0600 Subject: [PATCH 106/342] Fixed a typo in bridge logging statement. --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 58ef2e70..28865695 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -140,7 +140,7 @@ - (void)_flushMessageQueue { NSArray* messages = [messageQueueString componentsSeparatedByString:kMessageSeparator]; for (NSString *messageJSON in messages) { - [self _log:@"receivd" json:messageJSON]; + [self _log:@"received" json:messageJSON]; NSDictionary* message = [self _deserializeMessageJSON:messageJSON]; From 2f129dac1a842c80afaf6eecb6923985180d3fd9 Mon Sep 17 00:00:00 2001 From: jacob berkman Date: Fri, 27 Sep 2013 13:41:53 -0700 Subject: [PATCH 107/342] handle nil data in _sendData rather than each callHandler --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 1e4920a5..a540b0ec 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -56,7 +56,7 @@ - (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)respons } - (void)callHandler:(NSString *)handlerName { - [self callHandler:handlerName data:[NSNull null] responseCallback:nil]; + [self callHandler:handlerName data:nil responseCallback:nil]; } - (void)callHandler:(NSString *)handlerName data:(id)data { @@ -92,6 +92,9 @@ - (void)dealloc { } - (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { + if (!data) { + data = (NSDictionary *)[NSNull null]; + } NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; if (responseCallback) { From e75690e7fbca2439fc2f7a0357cb816e6a6137f5 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 27 Sep 2013 14:46:09 -0700 Subject: [PATCH 108/342] Clean up contributors list by using the github generated lists --- README.md | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 6edd5797..a309e453 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,12 @@ To use a WebViewJavascriptBridge in your own project: }) }, false) +Contributors & Forks +-------------------- +Contributors: https://github.com/marcuswestin/WebViewJavascriptBridge/graphs/contributors + +Forks: https://github.com/marcuswestin/WebViewJavascriptBridge/network/members + API Reference ------------- @@ -185,18 +191,3 @@ iOS4 support (with JSONKit) *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](https://github.com/johnezang/JSONKit/), and add `USE_JSONKIT` to the preprocessor macros for your project. - -Contributors ------------- -- [@marcuswestin](https://github.com/marcuswestin) Marcus Westin (Author) -- [@oakho](https://github.com/oakho) Antoine Lagadec (OS X version) -- [@psineur](https://github.com/psineur) Stepan Generalov -- [@sergiocampama](https://github.com/sergiocampama) Sergio Campamá -- [@stringbean](https://github.com/stringbean) Michael Stringer -- [@tanis2000](https://github.com/tanis2000) Valerio Santinelli -- [@drewburch](https://github.com/drewburch) Andrew Burch -- [@pj4533](https://github.com/pj4533) PJ Gray -- [@xzeror](https://github.com/xzeror) -- [@kelp404](https://github.com/kelp404) -- [@peyton](https://github.com/peyton) Peyton Randolph -- [@wangjinhua](https://github.com/wangjinhua) From 54300126b98bd604015e79ef1db4258cd6b67cf2 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 27 Sep 2013 14:46:15 -0700 Subject: [PATCH 109/342] v4.0.2 --- Changelog | 4 ++++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 632f803f..656786a5 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +v4.0.2 ++ Fix NSInvalidArgumentException: "attempt to insert nil object" when using shorthand -callHandler: ++ Fix sending messages including __WVJB_MESSAGE_SEPERATOR__ string + v4.0.1 + Fix detection of arc_weak support diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index ff4ac0bd..0f931ba0 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.0.1' + s.version = '4.0.2' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 92f90ab7fedda84621891d2abd777581b16c58d3 Mon Sep 17 00:00:00 2001 From: Miles Matthias Date: Thu, 24 Oct 2013 09:55:37 -0600 Subject: [PATCH 110/342] Added our Imbed repo to list of uses in the wild. See http://dojo4.com/blog/announcing-imbed-the-best-way-to-use-web-content-in-an-i-os-app --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a309e453..3a3bfdc6 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ WebViewJavascriptBridge is used by a range of companies and projects. This list - [Sush.io](http://www.sush.io) - Flutterby Labs - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) +- Dojo4's [Imbed](https://github.com/dojo4/imbed) Setup & Examples (iOS & OSX) ---------------------------- From d66f93e9f4a1d87d44dd949bdf99c68f30cb45a9 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 24 Oct 2013 15:35:31 -0700 Subject: [PATCH 111/342] Make log prefix capital SEND/RCVD --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index a540b0ec..e673d73a 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -119,7 +119,7 @@ - (void)_queueMessage:(NSDictionary *)message { - (void)_dispatchMessage:(NSDictionary *)message { NSString *messageJSON = [self _serializeMessage:message]; - [self _log:@"sending" json:messageJSON]; + [self _log:@"SEND" json:messageJSON]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; @@ -151,7 +151,7 @@ - (void)_flushMessageQueue { NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); continue; } - [self _log:@"receivd" json:message]; + [self _log:@"RCVD" json:message]; NSString* responseId = message[@"responseId"]; if (responseId) { From a91f2906950aa2612178c0b9a6730839da099eaf Mon Sep 17 00:00:00 2001 From: Bastian Bense Date: Fri, 25 Oct 2013 16:06:10 +0200 Subject: [PATCH 112/342] Fix exception if _sendData is called with data == nil --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index e673d73a..6935e389 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -95,7 +95,11 @@ - (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)re if (!data) { data = (NSDictionary *)[NSNull null]; } - NSMutableDictionary* message = [NSMutableDictionary dictionaryWithObject:data forKey:@"data"]; + NSMutableDictionary* message = [NSMutableDictionary dictionary]; + + if (data) { + message[@"data"] = data; + } if (responseCallback) { NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; From dc584db1e5c7958100c324881d96a57178945532 Mon Sep 17 00:00:00 2001 From: Miles Matthias Date: Fri, 25 Oct 2013 14:58:00 -0600 Subject: [PATCH 113/342] Replaced source code link to fancy project page for Imbed. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a3bfdc6..f28c52b3 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ WebViewJavascriptBridge is used by a range of companies and projects. This list - [Sush.io](http://www.sush.io) - Flutterby Labs - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) -- Dojo4's [Imbed](https://github.com/dojo4/imbed) +- Dojo4's [Imbed](http://dojo4.github.io/imbed/) Setup & Examples (iOS & OSX) ---------------------------- From c4cb6ab13c18a96db90906b7ea69b48eaa2ed5d0 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 16:56:32 -0700 Subject: [PATCH 114/342] The declared interface for WVJB expected data to be an `id`. However, the implementation assumed `NSDictionary` in a bunch of places. Furthermore, messages received from JS by ObjC were previously always forced into an `NSDictionary` but javascript did not replace null data packets with `{}`. This patch introduces consistency in all of these cases, assuming data to be `id` everywhere, and never changing the value of data. Drop JSONKit. It's 2013! --- Changelog | 4 ++++ .../WebViewJavascriptBridge.m | 24 +++++-------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Changelog b/Changelog index 656786a5..101de003 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +v4.1.0 ++ Allow for sending null/nil data packets ++ Drop support for JSONKit + v4.0.2 + Fix NSInvalidArgumentException: "attempt to insert nil object" when using shorthand -callHandler: + Fix sending messages including __WVJB_MESSAGE_SEPERATOR__ string diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 6935e389..fcce490f 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -47,11 +47,11 @@ + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WV return bridge; } -- (void)send:(NSDictionary *)data { +- (void)send:(id)data { [self send:data responseCallback:nil]; } -- (void)send:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback { +- (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { [self _sendData:data responseCallback:responseCallback handlerName:nil]; } @@ -91,10 +91,7 @@ - (void)dealloc { _messageHandler = nil; } -- (void)_sendData:(NSDictionary *)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { - if (!data) { - data = (NSDictionary *)[NSNull null]; - } +- (void)_sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { NSMutableDictionary* message = [NSMutableDictionary dictionary]; if (data) { @@ -188,8 +185,7 @@ - (void)_flushMessageQueue { } @try { - NSDictionary* data = message[@"data"]; - if (!data || ((id)data) == [NSNull null]) { data = [NSDictionary dictionary]; } + id data = message[@"data"]; handler(data, responseCallback); } @catch (NSException *exception) { @@ -199,20 +195,12 @@ - (void)_flushMessageQueue { } } -- (NSString *)_serializeMessage:(NSDictionary *)message { -#if defined _JSONKIT_H_ - return [message JSONString]; -#else +- (NSString *)_serializeMessage:(id)message { return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; -#endif } - (NSDictionary *)_deserializeMessageJSON:(NSString *)messageJSON { -#if defined _JSONKIT_H_ - return [messageJSON objectFromJSONString]; -#else - return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; -#endif + return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; } - (void)_log:(NSString *)action json:(id)json { From b68bc2680b00e7d10ef282275e2b2bf1e51b8bed Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 17:05:25 -0700 Subject: [PATCH 115/342] Use dictionary literals in example app --- Example Apps/ExampleApp-OSX/AppDelegate.m | 4 ++-- Example Apps/ExampleApp-iOS/ExampleAppDelegate.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m index d4b230c6..990f9779 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -38,7 +38,7 @@ - (void)_createBridge { NSLog(@"objc got response! %@", responseData); }]; - [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; + [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; } - (void)_createObjcButtons { @@ -64,7 +64,7 @@ - (void)_sendMessage { } - (void)_callHandler { - NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"]; + is data = @{ @"greetingFromObjC": @"Hi there, JS!" }; [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { NSLog(@"testJavascriptHandler responded: %@", response); }]; diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m index 11c6d310..944e4312 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m @@ -26,7 +26,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSLog(@"objc got response! %@", responseData); }]; - [_bridge callHandler:@"testJavascriptHandler" data:[NSDictionary dictionaryWithObject:@"before ready" forKey:@"foo"]]; + [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; [self renderButtons:webView]; [self loadExamplePage:webView]; @@ -58,7 +58,7 @@ - (void)sendMessage:(id)sender { } - (void)callHandler:(id)sender { - NSDictionary* data = [NSDictionary dictionaryWithObject:@"Hi there, JS!" forKey:@"greetingFromObjC"]; + id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { NSLog(@"testJavascriptHandler responded: %@", response); }]; From 5069f0849648f848648dfc2ec79b20a653943e54 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 17:07:22 -0700 Subject: [PATCH 116/342] Clean up internal representation of messages with a WVJBMessage typedef --- Changelog | 1 + WebViewJavascriptBridge/WebViewJavascriptBridge.m | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index 101de003..11ac8e4d 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,7 @@ v4.1.0 + Allow for sending null/nil data packets + Drop support for JSONKit ++ Clean up internal represenation of messages v4.0.2 + Fix NSInvalidArgumentException: "attempt to insert nil object" when using shorthand -callHandler: diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index fcce490f..8ee60d17 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -14,6 +14,7 @@ #define WVJB_WEAK __unsafe_unretained #endif +typedef NSDictionary WVJBMessage; @implementation WebViewJavascriptBridge { WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView; @@ -110,7 +111,7 @@ - (void)_sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallba [self _queueMessage:message]; } -- (void)_queueMessage:(NSDictionary *)message { +- (void)_queueMessage:(WVJBMessage*)message { if (_startupMessageQueue) { [_startupMessageQueue addObject:message]; } else { @@ -118,7 +119,7 @@ - (void)_queueMessage:(NSDictionary *)message { } } -- (void)_dispatchMessage:(NSDictionary *)message { +- (void)_dispatchMessage:(WVJBMessage*)message { NSString *messageJSON = [self _serializeMessage:message]; [self _log:@"SEND" json:messageJSON]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; @@ -147,8 +148,8 @@ - (void)_flushMessageQueue { NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messages class], messages); return; } - for (NSDictionary *message in messages) { - if (![message isKindOfClass:[NSDictionary class]]) { + for (WVJBMessage* message in messages) { + if (![message isKindOfClass:[WVJBMessage class]]) { NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); continue; } @@ -164,7 +165,7 @@ - (void)_flushMessageQueue { NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { - NSDictionary* msg = @{ @"responseId":callbackId, @"responseData":responseData }; + WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; [self _queueMessage:msg]; }; } else { @@ -199,7 +200,7 @@ - (NSString *)_serializeMessage:(id)message { return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; } -- (NSDictionary *)_deserializeMessageJSON:(NSString *)messageJSON { +- (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; } From fb46cc066a35ce861f40a530309fa2a3d3bddbe0 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 17:08:01 -0700 Subject: [PATCH 117/342] v4.1.0 --- WebViewJavascriptBridge.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 0f931ba0..227d89be 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.0.2' + s.version = '4.1.0' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 4d4fc9754a219358e894781a4ef243afe2c72146 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 17:26:18 -0700 Subject: [PATCH 118/342] Update JS initialization snippet. Fix #56 (Thanks @refractalize!). Possibly fixes #52. --- Example Apps/ExampleApp-OSX/AppDelegate.m | 2 +- Example Apps/ExampleApp.html | 17 +++++++++++++---- README.md | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m index 990f9779..4e77da67 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -64,7 +64,7 @@ - (void)_sendMessage { } - (void)_callHandler { - is data = @{ @"greetingFromObjC": @"Hi there, JS!" }; + id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { NSLog(@"testJavascriptHandler responded: %@", response); }]; diff --git a/Example Apps/ExampleApp.html b/Example Apps/ExampleApp.html index 30efb6c8..bf5b7bc7 100644 --- a/Example Apps/ExampleApp.html +++ b/Example Apps/ExampleApp.html @@ -12,9 +12,18 @@

WebViewJavascriptBridge Demo

window.onerror = function(err) { log('window.onerror: ' + err) } - document.addEventListener('WebViewJavascriptBridgeReady', onBridgeReady, false) - function onBridgeReady(event) { - var bridge = event.bridge + + function connectWebViewJavascriptBridge(callback) { + if (window.WebViewJavascriptBridge) { + callback(WebViewJavascriptBridge) + } else { + document.addEventListener('WebViewJavascriptBridgeReady', function() { + callback(WebViewJavascriptBridge) + }, false) + } + } + + connectWebViewJavascriptBridge(function(bridge) { var uniqueId = 1 function log(message, data) { var log = document.getElementById('log') @@ -60,7 +69,7 @@

WebViewJavascriptBridge Demo

log('JS got response', response) }) } - } + })
diff --git a/README.md b/README.md index f28c52b3..ef6eb762 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,20 @@ To use a WebViewJavascriptBridge in your own project: 4) Finally, set up the javascript side: - document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) { - var bridge = event.bridge + 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) { @@ -62,7 +74,7 @@ To use a WebViewJavascriptBridge in your own project: bridge.send('Please respond to this', function responseCallback(responseData) { console.log("Javascript got its response", responseData) }) - }, false) + }) Contributors & Forks -------------------- From 3e8e51bc62cf9c26a903311b3b74d8919d971a81 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 25 Oct 2013 17:28:23 -0700 Subject: [PATCH 119/342] Changelog for upcoming v4.1.1 --- Changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog b/Changelog index 11ac8e4d..45f82014 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +intended v4.1.1 ++ Better JS initialization script (thank @refractalize!) + v4.1.0 + Allow for sending null/nil data packets + Drop support for JSONKit From 197bab4152d8ae6e8adfdd65392655cd17bc73d0 Mon Sep 17 00:00:00 2001 From: Bastian Bense Date: Sat, 26 Oct 2013 11:14:17 +0200 Subject: [PATCH 120/342] Fix resource path in podspec --- WebViewJavascriptBridge.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 227d89be..f4d86f8b 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.osx.platform = :osx s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}' s.osx.source_files = 'WebViewJavascriptBridge/*.{h,m}' - s.resource = 'WebViewJavascriptBridgeAbstract/WebViewJavascriptBridge.js.txt' + s.resource = 'WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt' s.ios.framework = 'UIKit' s.osx.framework = 'WebKit' end From 01eb1aa8cb5fab2b4f60ff462e8e55088d9661e8 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 26 Nov 2013 10:38:33 -0800 Subject: [PATCH 121/342] Migrate to latest XCode-recommended settings --- Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index b71010e5..7ae53eda 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -139,7 +139,7 @@ 2CEB3EB21602563600548120 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0500; ORGANIZATIONNAME = "Marcus Westin"; }; buildConfigurationList = 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp-iOS" */; @@ -220,6 +220,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 6.0; + ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; From f5b48ee40e1bc92f1df49924e13c6b3b7b96c3fc Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 26 Nov 2013 10:39:16 -0800 Subject: [PATCH 122/342] Add example for webViewDidStartLoad:/webViewDidFinishLoad: to example app. References GH issue #61 --- Example Apps/ExampleApp-iOS/ExampleAppDelegate.h | 2 +- Example Apps/ExampleApp-iOS/ExampleAppDelegate.m | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h index 5fc2d78b..d85c5e94 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h @@ -1,7 +1,7 @@ #import #import "WebViewJavascriptBridge.h" -@interface ExampleAppDelegate : UIResponder +@interface ExampleAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge; diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m index 944e4312..a41b51c2 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m @@ -5,6 +5,14 @@ @implementation ExampleAppDelegate @synthesize window = _window; @synthesize javascriptBridge = _bridge; +- (void)webViewDidStartLoad:(UIWebView *)webView { + NSLog(@"webViewDidStartLoad"); +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + NSLog(@"webViewDidFinishLoad"); +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; @@ -12,7 +20,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [WebViewJavascriptBridge enableLogging]; - _bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) { + _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"ObjC received message from JS: %@", data); responseCallback(@"Response for message from ObjC"); }]; From cd1b1a71c157bfe59aa839408b5e613b78bfe92c Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 6 Dec 2013 13:26:23 -0800 Subject: [PATCH 123/342] Remove left/right landscape orientation support --- Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist | 2 -- 1 file changed, 2 deletions(-) diff --git a/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist b/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist index 2e36c495..81d25998 100644 --- a/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist +++ b/Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist @@ -31,8 +31,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight From 4b95cde27472bc54b36556238561a050f4b94285 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Mon, 13 Jan 2014 15:33:05 -0800 Subject: [PATCH 124/342] Have the example iOS app use a UIViewController instead of adding the webview directly to the app window. Fixes #65 on GH --- .../ExampleApp-iOS.xcodeproj/project.pbxproj | 6 ++ .../ExampleApp-iOS/ExampleAppDelegate.h | 11 +-- .../ExampleApp-iOS/ExampleAppDelegate.m | 72 +-------------- .../ExampleApp-iOS/ExampleAppViewController.h | 13 +++ .../ExampleApp-iOS/ExampleAppViewController.m | 88 +++++++++++++++++++ 5 files changed, 111 insertions(+), 79 deletions(-) create mode 100644 Example Apps/ExampleApp-iOS/ExampleAppViewController.h create mode 100644 Example Apps/ExampleApp-iOS/ExampleAppViewController.m diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 7ae53eda..4834adaf 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */; }; 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; }; + 2C45CA2C1884AD520002A4E2 /* ExampleAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C45CA2B1884AD520002A4E2 /* ExampleAppViewController.m */; }; 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045B717117439006DEE8B /* InfoPlist.strings */; }; 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; }; 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; }; @@ -23,6 +24,8 @@ 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; + 2C45CA2A1884AD520002A4E2 /* ExampleAppViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppViewController.h; sourceTree = ""; }; + 2C45CA2B1884AD520002A4E2 /* ExampleAppViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppViewController.m; sourceTree = ""; }; 2CA045B817117439006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ExampleApp-iOS-Info.plist"; sourceTree = ""; }; 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-iOS-Prefix.pch"; sourceTree = ""; }; @@ -68,6 +71,8 @@ 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, + 2C45CA2A1884AD520002A4E2 /* ExampleAppViewController.h */, + 2C45CA2B1884AD520002A4E2 /* ExampleAppViewController.m */, 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */, 2CA046211711A94E006DEE8B /* Supporting Files */, ); @@ -179,6 +184,7 @@ buildActionMask = 2147483647; files = ( 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */, + 2C45CA2C1884AD520002A4E2 /* ExampleAppViewController.m in Sources */, 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, ); diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h index d85c5e94..f59015d8 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.h @@ -1,12 +1,5 @@ #import -#import "WebViewJavascriptBridge.h" - -@interface ExampleAppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; -@property (strong, nonatomic) WebViewJavascriptBridge *javascriptBridge; - -- (void)renderButtons:(UIWebView*)webView; -- (void)loadExamplePage:(UIWebView*)webView; +@interface ExampleAppDelegate : UIResponder +@property (nonatomic) UIWindow *window; @end diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m index a41b51c2..72f35ded 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m @@ -1,81 +1,13 @@ #import "ExampleAppDelegate.h" +#import "ExampleAppViewController.h" @implementation ExampleAppDelegate -@synthesize window = _window; -@synthesize javascriptBridge = _bridge; - -- (void)webViewDidStartLoad:(UIWebView *)webView { - NSLog(@"webViewDidStartLoad"); -} - -- (void)webViewDidFinishLoad:(UIWebView *)webView { - NSLog(@"webViewDidFinishLoad"); -} - - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - UIWebView* webView = [[UIWebView alloc] initWithFrame:self.window.bounds]; - [self.window addSubview:webView]; - - [WebViewJavascriptBridge enableLogging]; - - _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"ObjC received message from JS: %@", data); - responseCallback(@"Response for message from ObjC"); - }]; - - [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"testObjcCallback called: %@", data); - responseCallback(@"Response from testObjcCallback"); - }]; - - [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) { - NSLog(@"objc got response! %@", responseData); - }]; - - [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; - - [self renderButtons:webView]; - [self loadExamplePage:webView]; - - [_bridge send:@"A string sent from ObjC after Webview has loaded."]; - + self.window.rootViewController = [ExampleAppViewController new]; [self.window makeKeyAndVisible]; return YES; } -- (void)renderButtons:(UIWebView*)webView { - UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; - [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:messageButton aboveSubview:webView]; - messageButton.frame = CGRectMake(20, 414, 130, 45); - - UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; - [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; - [self.window insertSubview:callbackButton aboveSubview:webView]; - callbackButton.frame = CGRectMake(170, 414, 130, 45); -} - -- (void)sendMessage:(id)sender { - [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) { - NSLog(@"sendMessage got response: %@", response); - }]; -} - -- (void)callHandler:(id)sender { - id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; - [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { - NSLog(@"testJavascriptHandler responded: %@", response); - }]; -} - -- (void)loadExamplePage:(UIWebView*)webView { - NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; - NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; - [webView loadHTMLString:appHtml baseURL:nil]; -} - @end diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.h b/Example Apps/ExampleApp-iOS/ExampleAppViewController.h new file mode 100644 index 00000000..d2e25c2d --- /dev/null +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.h @@ -0,0 +1,13 @@ +// +// ExampleAppViewController.h +// ExampleApp-iOS +// +// Created by Marcus Westin on 1/13/14. +// Copyright (c) 2014 Marcus Westin. All rights reserved. +// + +#import + +@interface ExampleAppViewController : UINavigationController + +@end diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m new file mode 100644 index 00000000..b9243d61 --- /dev/null +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m @@ -0,0 +1,88 @@ +// +// ExampleAppViewController.m +// ExampleApp-iOS +// +// Created by Marcus Westin on 1/13/14. +// Copyright (c) 2014 Marcus Westin. All rights reserved. +// + +#import "ExampleAppViewController.h" +#import "WebViewJavascriptBridge.h" + +@interface ExampleAppViewController () +@property WebViewJavascriptBridge* bridge; +@end + +@implementation ExampleAppViewController + +- (void)viewWillAppear:(BOOL)animated { + if (_bridge) { return; } + + UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; + [self.view addSubview:webView]; + + [WebViewJavascriptBridge enableLogging]; + + _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"ObjC received message from JS: %@", data); + responseCallback(@"Response for message from ObjC"); + }]; + + [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"testObjcCallback called: %@", data); + responseCallback(@"Response from testObjcCallback"); + }]; + + [_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) { + NSLog(@"objc got response! %@", responseData); + }]; + + [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; + + [self renderButtons:webView]; + [self loadExamplePage:webView]; + + [_bridge send:@"A string sent from ObjC after Webview has loaded."]; +} + +- (void)webViewDidStartLoad:(UIWebView *)webView { + NSLog(@"webViewDidStartLoad"); +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + NSLog(@"webViewDidFinishLoad"); +} + +- (void)renderButtons:(UIWebView*)webView { + UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; + [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; + [self.view insertSubview:messageButton aboveSubview:webView]; + messageButton.frame = CGRectMake(20, 414, 130, 45); + + UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; + [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; + [self.view insertSubview:callbackButton aboveSubview:webView]; + callbackButton.frame = CGRectMake(170, 414, 130, 45); +} + +- (void)sendMessage:(id)sender { + [_bridge send:@"A string sent from ObjC to JS" responseCallback:^(id response) { + NSLog(@"sendMessage got response: %@", response); + }]; +} + +- (void)callHandler:(id)sender { + id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; + [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { + NSLog(@"testJavascriptHandler responded: %@", response); + }]; +} + +- (void)loadExamplePage:(UIWebView*)webView { + NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; + NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; + [webView loadHTMLString:appHtml baseURL:nil]; +} +@end From bae8975aeb3d769e65f6b662133538cc1defa805 Mon Sep 17 00:00:00 2001 From: Joao Antunes Date: Tue, 4 Feb 2014 19:04:38 +0000 Subject: [PATCH 125/342] Facebook Paper use of the bridge Updated the Readme with Facebook Paper app usage. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ef6eb762..9047233b 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ In the Wild ----------- 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 Paper](https://facebook.com/paper) - [Yardsale](https://www.getyardsale.com/) - [EverTrue](http://www.evertrue.com/) - [Game Insight](http://www.game-insight.com/) From 5183c4c848d2f9ce3d575081922ba7123edc2608 Mon Sep 17 00:00:00 2001 From: Kamil Burczyk Date: Sun, 9 Feb 2014 17:07:26 +0100 Subject: [PATCH 126/342] Added possibility to set custom bundle where core bridge.js script is located --- .../WebViewJavascriptBridge.h | 1 + .../WebViewJavascriptBridge.m | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index d2d0544b..baa341c8 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -29,6 +29,7 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; + (void)enableLogging; - (void)send:(id)message; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 8ee60d17..2473c01e 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -25,6 +25,8 @@ @implementation WebViewJavascriptBridge { long _uniqueId; WVJBHandler _messageHandler; + NSBundle *_resourceBundle; + #if defined WVJB_PLATFORM_IOS NSUInteger _numRequestsLoading; #endif @@ -42,8 +44,13 @@ + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandle } + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler { + return [self bridgeForWebView:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:nil]; +} + ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle +{ WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; - [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler]; + [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; [bridge reset]; return bridge; } @@ -222,7 +229,7 @@ - (void)_log:(NSString *)action json:(id)json { **********************************/ #if defined WVJB_PLATFORM_OSX -- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler { +- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{ _messageHandler = messageHandler; _webView = webView; _webViewDelegate = webViewDelegate; @@ -231,6 +238,8 @@ - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJ _webView.frameLoadDelegate = self; _webView.resourceLoadDelegate = self; _webView.policyDelegate = self; + + _resourceBundle = bundle; } - (void) _platformSpecificDealloc { @@ -244,7 +253,8 @@ - (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)frame if (webView != _webView) { return; } if (![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSBundle *bundle = _resourceBundle ? _resourceBundle : [NSBundle mainBundle]; + NSString *filePath = [bundle pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:js]; } @@ -312,12 +322,13 @@ - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendReq **********************************/ #elif defined WVJB_PLATFORM_IOS -- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler { +- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{ _messageHandler = messageHandler; _webView = webView; _webViewDelegate = webViewDelegate; _messageHandlers = [NSMutableDictionary dictionary]; _webView.delegate = self; + _resourceBundle = bundle; } - (void) _platformSpecificDealloc { @@ -330,7 +341,8 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { _numRequestsLoading--; if (_numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:@"typeof WebViewJavascriptBridge == 'object'"] isEqualToString:@"true"]) { - NSString *filePath = [[NSBundle mainBundle] pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSBundle *bundle = _resourceBundle ? _resourceBundle : [NSBundle mainBundle]; + NSString *filePath = [bundle pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:js]; } From f3e0c6acb031b9479f8f533015b7a06c81b51306 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Mon, 10 Feb 2014 09:41:13 -0800 Subject: [PATCH 127/342] Add Facebook Messenger to products/companies using WVJB. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9047233b..5af2b3ce 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ In the Wild ----------- 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](https://www.facebook.com/mobile/messenger) - [Facebook Paper](https://facebook.com/paper) - [Yardsale](https://www.getyardsale.com/) - [EverTrue](http://www.evertrue.com/) From 16aa68e271e334c1aaf0424737953a6c83280d28 Mon Sep 17 00:00:00 2001 From: shuizhongyueming Date: Sat, 22 Feb 2014 00:09:26 +0800 Subject: [PATCH 128/342] add a method,make the user can decide whether the request from webview should be load except the WVJB request --- .../WebViewJavascriptBridge.h | 15 +++++++++++++ .../WebViewJavascriptBridge.m | 21 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index baa341c8..dede2189 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -22,13 +22,28 @@ #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject #endif +@protocol WebViewJavascriptBridgeDelegate + +@optional + +// define a method,make the user decide every request from webview should be load except the WVJB request +-(BOOL) WVJB_webView:(UIWebView *)webView +shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType; + + +@end + typedef void (^WVJBResponseCallback)(id responseData); typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_TYPE +@property (nonatomic,weak) id delegate; + + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView WVJBDelegate:(id)delegate handler:(WVJBHandler)handler; + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; + (void)enableLogging; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 2473c01e..919e119b 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -52,6 +52,15 @@ + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WV WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; [bridge reset]; + bridge.delegate = nil; + return bridge; +} + ++ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView WVJBDelegate:(id)delegate handler:(WVJBHandler)handler { + WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; + [bridge _platformSpecificSetup:webView webViewDelegate:nil handler:handler]; + [bridge reset]; + bridge.delegate = delegate; return bridge; } @@ -385,7 +394,17 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; } else { - return YES; + if(self.delegate){ + if([self.delegate respondsToSelector:@selector(WVJB_webView:shouldStartLoadWithRequest:navigationType:)]){ + return [self.delegate WVJB_webView:webView + shouldStartLoadWithRequest:request + navigationType:navigationType]; + }else{ + return YES; + } + }else{ + return YES; + } } } From 1dc02737d14c75d6d30f2aa792937a4199e04345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=9C=E5=B0=98?= Date: Wed, 12 Mar 2014 10:53:59 +0800 Subject: [PATCH 129/342] prevent insert nil into dic --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 2473c01e..2d707e8a 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -172,6 +172,10 @@ - (void)_flushMessageQueue { NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { + if (responseData == nil) { + responseData = @{}; + } + WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; [self _queueMessage:msg]; }; From 92d4715ff3f0725a37c91354d576f47771f07935 Mon Sep 17 00:00:00 2001 From: Johan Kanflo Date: Sat, 29 Mar 2014 09:49:00 +0100 Subject: [PATCH 130/342] #74 Not possible to load external javascript in ExampleApp.html --- Example Apps/ExampleApp-iOS/ExampleAppViewController.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m index b9243d61..c81e136a 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m @@ -83,6 +83,7 @@ - (void)callHandler:(id)sender { - (void)loadExamplePage:(UIWebView*)webView { NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; - [webView loadHTMLString:appHtml baseURL:nil]; + NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; + [webView loadHTMLString:appHtml baseURL:baseURL]; } @end From 4c34caa104e2213928dcbfe862ed2aba1119b89a Mon Sep 17 00:00:00 2001 From: Kamil Burczyk Date: Thu, 3 Apr 2014 14:26:17 +0200 Subject: [PATCH 131/342] Updated Readme with custom bundle example --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 5af2b3ce..5012ff33 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,23 @@ Example: NSLog(@"Current UIWebView page URL is: %@", responseData); }]; +#### Custom bundle +`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"]] +]; +``` ### Javascript API From 1aa0ecfb83cb97ee5c1efbfa28b2948aa3801069 Mon Sep 17 00:00:00 2001 From: Nolan Waite Date: Wed, 16 Apr 2014 03:16:13 -0300 Subject: [PATCH 132/342] Escape U+2028 and U+2029 when writing JSON as a JavaScript string literal. U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR are also not allowed in a JavaScript string literal. Trying to send a message with either would cause an "unexpected EOF" exception on the JavaScript side. --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 2473c01e..0f1e314a 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -135,6 +135,8 @@ - (void)_dispatchMessage:(WVJBMessage*)message { messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; if ([[NSThread currentThread] isMainThread]) { From b8d5856a758f1b66e2f0e6dcb557ba8542a950be Mon Sep 17 00:00:00 2001 From: Nolan Waite Date: Tue, 15 Apr 2014 23:30:56 -0700 Subject: [PATCH 133/342] Fix little typo in comment --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 2473c01e..805cbc5c 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -318,7 +318,7 @@ - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendReq -/* Platform specific internals: OSX +/* Platform specific internals: iOS **********************************/ #elif defined WVJB_PLATFORM_IOS From 18b51d212191d38dd237b47b7ad22d05b0060a25 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 22 May 2014 19:56:53 +0200 Subject: [PATCH 134/342] Upgrade to latest recommended xcode settings for example OSX project ("Automatically detect target architecture") --- Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index 1a78a146..0e947166 100644 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -152,7 +152,7 @@ 2C136A1917641106004C7401 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0510; ORGANIZATIONNAME = "Marcus Westin"; }; buildConfigurationList = 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */; @@ -224,7 +224,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -257,7 +256,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; From 6da9284f76e59dcd72ca8dc0878c7f4fa5001484 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 22 May 2014 20:12:16 +0200 Subject: [PATCH 135/342] Revert "Merge pull request #70 from shuizhongyueming/master" This reverts commit 49579d689e23e7326260f5076764affe8f11c3e2, reversing changes made to 18b51d212191d38dd237b47b7ad22d05b0060a25. The added changes only worked for iOS projects, but broke OSX builds. --- .../WebViewJavascriptBridge.h | 15 ------------- .../WebViewJavascriptBridge.m | 21 +------------------ 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index dede2189..baa341c8 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -22,28 +22,13 @@ #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject #endif -@protocol WebViewJavascriptBridgeDelegate - -@optional - -// define a method,make the user decide every request from webview should be load except the WVJB request --(BOOL) WVJB_webView:(UIWebView *)webView -shouldStartLoadWithRequest:(NSURLRequest *)request - navigationType:(UIWebViewNavigationType)navigationType; - - -@end - typedef void (^WVJBResponseCallback)(id responseData); typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_TYPE -@property (nonatomic,weak) id delegate; - + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; -+ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView WVJBDelegate:(id)delegate handler:(WVJBHandler)handler; + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; + (void)enableLogging; diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 08a0fb66..4addea33 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -52,15 +52,6 @@ + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WV WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; [bridge reset]; - bridge.delegate = nil; - return bridge; -} - -+ (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView WVJBDelegate:(id)delegate handler:(WVJBHandler)handler { - WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; - [bridge _platformSpecificSetup:webView webViewDelegate:nil handler:handler]; - [bridge reset]; - bridge.delegate = delegate; return bridge; } @@ -396,17 +387,7 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; } else { - if(self.delegate){ - if([self.delegate respondsToSelector:@selector(WVJB_webView:shouldStartLoadWithRequest:navigationType:)]){ - return [self.delegate WVJB_webView:webView - shouldStartLoadWithRequest:request - navigationType:navigationType]; - }else{ - return YES; - } - }else{ - return YES; - } + return YES; } } From 8a60345a424a857473acb044ca712e713fb14e25 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 23 May 2014 16:24:06 +0200 Subject: [PATCH 136/342] If a response callback gets called with a `nil` response value, then replace that value with `[NSNull null]` instead of `@{}`. This way the javascript will receive a `null` value instead of `{}`. See gh pr #73 --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 02ff7b2d..e6584568 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -175,7 +175,7 @@ - (void)_flushMessageQueue { if (callbackId) { responseCallback = ^(id responseData) { if (responseData == nil) { - responseData = @{}; + responseData = [NSNull null]; } WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; From 328f341bbdf27fc9ec4f57d2f28512d950fc6651 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 23 May 2014 16:24:27 +0200 Subject: [PATCH 137/342] Always print the received response value, even if it is null --- Example Apps/ExampleApp.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example Apps/ExampleApp.html b/Example Apps/ExampleApp.html index bf5b7bc7..d31f1fb1 100644 --- a/Example Apps/ExampleApp.html +++ b/Example Apps/ExampleApp.html @@ -29,7 +29,7 @@

WebViewJavascriptBridge Demo

var log = document.getElementById('log') var el = document.createElement('div') el.className = 'logLine' - el.innerHTML = uniqueId++ + '. ' + message + (data ? ':
' + JSON.stringify(data) : '') + el.innerHTML = uniqueId++ + '. ' + message + ':
' + JSON.stringify(data) if (log.children.length) { log.insertBefore(el, log.children[0]) } else { log.appendChild(el) } } From 0c2bf6248a2aa84c435a746b58eb2f02120d3308 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 23 May 2014 16:25:56 +0200 Subject: [PATCH 138/342] Changelog --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index 45f82014..ce17addf 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,6 @@ intended v4.1.1 + Better JS initialization script (thank @refractalize!) ++ When passing nil to an objc response callback, replace it with [NSNull null] (becomes null in js) v4.1.0 + Allow for sending null/nil data packets From dba418a4d5ac40ffc52bba5637c7a23dfb8c64c4 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 23 May 2014 16:26:15 +0200 Subject: [PATCH 139/342] bump copyright date --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 1e732703..c44f4d9a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2013 Marcus Westin, Antoine Lagadec +Copyright (c) 2011-2014 Marcus Westin, Antoine Lagadec Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation From da91f9b54c3ae41fd1597f2d2b95bec97ae6295a Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 23 May 2014 16:26:44 +0200 Subject: [PATCH 140/342] v4.1.1 --- Changelog | 2 +- WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index ce17addf..f10fbc74 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,4 @@ -intended v4.1.1 +v4.1.1 + Better JS initialization script (thank @refractalize!) + When passing nil to an objc response callback, replace it with [NSNull null] (becomes null in js) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index f4d86f8b..0b5172b1 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.1.0' + s.version = '4.1.1' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 48f88cf07d4eea63d15676b913d3d768041189c7 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 27 Jun 2014 23:51:03 -0400 Subject: [PATCH 141/342] Ensure that the iframe has a source set before appending it to the DOM. This fixes the problems described in github issue #86, where webViewDidStart/FinishLoad were called twice and isLoading was always true. --- WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt index 86303713..12a8700e 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt @@ -14,6 +14,7 @@ function _createQueueReadyIframe(doc) { messagingIframe = doc.createElement('iframe') messagingIframe.style.display = 'none' + messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE doc.documentElement.appendChild(messagingIframe) } From 083e876b25dee2c5d22215f21728f49289721252 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Mon, 30 Jun 2014 14:47:35 -0400 Subject: [PATCH 142/342] v4.1.2 --- Changelog | 3 +++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index f10fbc74..c7ddfdb4 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +v4.1.2 ++ Fix bug: webViewDidStart/FinishLoad were called twice and isLoading was always true (#86) + v4.1.1 + Better JS initialization script (thank @refractalize!) + When passing nil to an objc response callback, replace it with [NSNull null] (becomes null in js) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 0b5172b1..ac82c5a5 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.1.1' + s.version = '4.1.2' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From 4f05b6d88fab7aae34ea13ec09d28de975051e87 Mon Sep 17 00:00:00 2001 From: Pushpak Rangaiah Date: Wed, 9 Jul 2014 22:04:23 +0530 Subject: [PATCH 143/342] Added tag to PodFile git source path Required for PodFile to pass validation and to push updates. --- WebViewJavascriptBridge.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index ac82c5a5..74a55a8e 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } s.requires_arc = true - s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git' } + s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git', :tag => s.version.to_s } s.ios.platform = :ios, '5.0' s.osx.platform = :osx s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}' From 876a1a2e2162955c1da64f96a788b36fadcc8d53 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Thu, 10 Jul 2014 09:20:57 -0400 Subject: [PATCH 144/342] v4.1.3 --- Changelog | 3 +++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index c7ddfdb4..cf3b7731 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +v4.1.3 ++ Update podspec file with tag + v4.1.2 + Fix bug: webViewDidStart/FinishLoad were called twice and isLoading was always true (#86) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index 74a55a8e..f3345073 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.1.2' + s.version = '4.1.3' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From ddb38a16f0db33ed6d678034d53f0fd2e685c314 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 15 Jul 2014 22:22:55 -0400 Subject: [PATCH 145/342] Update podspec to make `pod trunk push` work as expected --- WebViewJavascriptBridge.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index f3345073..de25a58a 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -2,11 +2,11 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' s.version = '4.1.3' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' - s.homepage = 'http://github.com/marcuswestin/WebViewJavascriptBridge' + s.homepage = 'https://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } s.requires_arc = true - s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git', :tag => s.version.to_s } + s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git', :tag => 'v'+s.version.to_s } s.ios.platform = :ios, '5.0' s.osx.platform = :osx s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}' From 5b5a6e81fa97addd1f2c033590fb4856a6092f3a Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Tue, 15 Jul 2014 22:29:02 -0400 Subject: [PATCH 146/342] Annotate Changelog with release checklist --- Changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Changelog b/Changelog index cf3b7731..6b7d8faf 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,18 @@ +WebViewJavascriptBridge Changelog +================================= + +Release Checklist +----------------- +- gitu-update +- Note Changelog +- Bump `WebViewJavascriptBridge.podspec` version "X.Y.Z" +- gitm-commit "vX.Y.Z" +- gitt-tag "vX.Y.Z" +- pod trunk push + +Version History +--------------- + v4.1.3 + Update podspec file with tag From 553c77b43461ea21445c85027cdd9e70320398d5 Mon Sep 17 00:00:00 2001 From: Victor Ilyukevich Date: Thu, 17 Jul 2014 01:05:36 +0300 Subject: [PATCH 147/342] Add CareZone to the list who use the library --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5012ff33..8420c7ec 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ WebViewJavascriptBridge is used by a range of companies and projects. This list - Flutterby Labs - JD Media's [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) - Dojo4's [Imbed](http://dojo4.github.io/imbed/) +- [CareZone](https://carezone.com) Setup & Examples (iOS & OSX) ---------------------------- From 40eda37cff0c96d259e56e8faa7542ab523949c7 Mon Sep 17 00:00:00 2001 From: J Spencer Date: Tue, 22 Jul 2014 16:05:59 -0700 Subject: [PATCH 148/342] Removed extra format specifier --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8420c7ec..f36b17b0 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ To use a WebViewJavascriptBridge in your own project: [bridge send:@"Well hello there"]; [bridge send:[NSDictionary dictionaryWithObject:@"Foo" forKey:@"Bar"]]; [bridge send:@"Give me a response, will you?" responseCallback:^(id responseData) { - NSLog(@"ObjC got its response! %@ %@", responseData); + NSLog(@"ObjC got its response! %@", responseData); }]; 4) Finally, set up the javascript side: From 05891801d46ef5f3c049231c5e050f3fb79c2585 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Fri, 1 Aug 2014 12:15:34 -0400 Subject: [PATCH 149/342] Add button in example app to reload webview, to show that reloading the webview works. (See gh issue #94) --- .../ExampleApp-iOS/ExampleAppViewController.m | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m index c81e136a..3f1f7794 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m @@ -54,17 +54,29 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { } - (void)renderButtons:(UIWebView*)webView { + UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; + UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [messageButton setTitle:@"Send message" forState:UIControlStateNormal]; [messageButton addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; [self.view insertSubview:messageButton aboveSubview:webView]; - messageButton.frame = CGRectMake(20, 414, 130, 45); - + messageButton.frame = CGRectMake(10, 414, 100, 35); + messageButton.titleLabel.font = font; + messageButton.backgroundColor = [UIColor colorWithWhite:1 alpha:0.75]; + UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; [self.view insertSubview:callbackButton aboveSubview:webView]; - callbackButton.frame = CGRectMake(170, 414, 130, 45); + callbackButton.frame = CGRectMake(110, 414, 100, 35); + callbackButton.titleLabel.font = font; + + UIButton* reloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [reloadButton setTitle:@"Reload webview" forState:UIControlStateNormal]; + [reloadButton addTarget:webView action:@selector(reload) forControlEvents:UIControlEventTouchUpInside]; + [self.view insertSubview:reloadButton aboveSubview:webView]; + reloadButton.frame = CGRectMake(210, 414, 100, 35); + reloadButton.titleLabel.font = font; } - (void)sendMessage:(id)sender { From 10a214bcb9f1e844ceda9fd7797cdcc1db9dfbab Mon Sep 17 00:00:00 2001 From: Ruslan Skorb Date: Tue, 5 Aug 2014 19:23:06 +0300 Subject: [PATCH 150/342] [Fix] Import for iOS. Important for static libraries that do not import in the Precompiled Header (pch). --- WebViewJavascriptBridge/WebViewJavascriptBridge.h | 1 + 1 file changed, 1 insertion(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index baa341c8..6b0334b1 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -17,6 +17,7 @@ #define WVJB_WEBVIEW_TYPE WebView #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject #elif defined __IPHONE_OS_VERSION_MAX_ALLOWED + #import #define WVJB_PLATFORM_IOS #define WVJB_WEBVIEW_TYPE UIWebView #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject From 68a37a2287e1590a8d7ab25181db8be4021da9a6 Mon Sep 17 00:00:00 2001 From: Ruslan Skorb Date: Tue, 5 Aug 2014 19:28:21 +0300 Subject: [PATCH 151/342] [Fix] App crash when no handler (_messageHandler) for message from JS. --- WebViewJavascriptBridge/WebViewJavascriptBridge.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index e6584568..6dac3016 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -196,6 +196,10 @@ - (void)_flushMessageQueue { } } else { handler = _messageHandler; + if (!handler) { + NSLog(@"WVJB Warning: No handler for message from JS: %@", message); + return responseCallback(@{}); + } } @try { From 9294201de4f4a6759a41e3975c18bc6d7f104562 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 27 Aug 2014 13:05:10 -0400 Subject: [PATCH 152/342] Simplify no-handler case: throw exception any time there is no handler for a message. Similarly, let runtime exceptions inside handlers bubble up and be caught by webkit instead of simply logging them in WVJB. References GH PR #97 --- .../WebViewJavascriptBridge.m | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 6dac3016..388b0494 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -190,25 +190,15 @@ - (void)_flushMessageQueue { WVJBHandler handler; if (message[@"handlerName"]) { handler = _messageHandlers[message[@"handlerName"]]; - if (!handler) { - NSLog(@"WVJB Warning: No handler for %@", message[@"handlerName"]); - return responseCallback(@{}); - } } else { handler = _messageHandler; - if (!handler) { - NSLog(@"WVJB Warning: No handler for message from JS: %@", message); - return responseCallback(@{}); - } } - - @try { - id data = message[@"data"]; - handler(data, responseCallback); - } - @catch (NSException *exception) { - NSLog(@"WebViewJavascriptBridge: WARNING: objc handler threw. %@ %@", message, exception); + + if (!handler) { + [NSException raise:@"WVJBNoHandlerException" format:@"No handler for message from JS: %@", message]; } + + handler(message[@"data"], responseCallback); } } } From 646def3b11c19b943cc716894f1604d357c7ca09 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 27 Aug 2014 13:07:10 -0400 Subject: [PATCH 153/342] v4.1.4 --- Changelog | 4 ++++ WebViewJavascriptBridge.podspec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 6b7d8faf..b19f6cfe 100644 --- a/Changelog +++ b/Changelog @@ -13,6 +13,10 @@ Release Checklist Version History --------------- +v4.1.4 ++ Improve how WVJB handles the case when there is no ObjC handler for a message received from js. ++ If an objc handler throws and exception, let it bubble up to the webkit engine instead of catching it in WVJB. + v4.1.3 + Update podspec file with tag diff --git a/WebViewJavascriptBridge.podspec b/WebViewJavascriptBridge.podspec index de25a58a..fbb16a8b 100644 --- a/WebViewJavascriptBridge.podspec +++ b/WebViewJavascriptBridge.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'WebViewJavascriptBridge' - s.version = '4.1.3' + s.version = '4.1.4' s.summary = 'An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews.' s.homepage = 'https://github.com/marcuswestin/WebViewJavascriptBridge' s.license = { :type => 'MIT', :file => 'LICENSE' } From dcecc1186719bd701a753360478c99835026fa2a Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 27 Aug 2014 13:10:56 -0400 Subject: [PATCH 154/342] Remove WebViewJavascriptBridge `-reset` method. It is unreliable and should not be used. See GH issue #99 --- Changelog | 3 +++ .../WebViewJavascriptBridge.h | 1 - .../WebViewJavascriptBridge.m | 16 +++++++++------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Changelog b/Changelog index b19f6cfe..9553abaf 100644 --- a/Changelog +++ b/Changelog @@ -13,6 +13,9 @@ Release Checklist Version History --------------- +Intended v5.0.0 ++ Removed `WebViewJavascriptBridge -reset`. It should never have been exposed as a public API. + v4.1.4 + Improve how WVJB handles the case when there is no ObjC handler for a message received from js. + If an objc handler throws and exception, let it bubble up to the webkit engine instead of catching it in WVJB. diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 6b0334b1..9e90829f 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -39,6 +39,5 @@ typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); - (void)callHandler:(NSString*)handlerName; - (void)callHandler:(NSString*)handlerName data:(id)data; - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; -- (void)reset; @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 388b0494..04ab38ee 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -51,7 +51,6 @@ + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WV { WebViewJavascriptBridge* bridge = [[WebViewJavascriptBridge alloc] init]; [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; - [bridge reset]; return bridge; } @@ -79,15 +78,18 @@ - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { _messageHandlers[handlerName] = [handler copy]; } -- (void)reset { - _startupMessageQueue = [NSMutableArray array]; - _responseCallbacks = [NSMutableDictionary dictionary]; - _uniqueId = 0; -} - /* Platform agnostic internals *****************************/ +- (id)init { + if (self = [super init]) { + _startupMessageQueue = [NSMutableArray array]; + _responseCallbacks = [NSMutableDictionary dictionary]; + _uniqueId = 0; + } + return self; +} + - (void)dealloc { [self _platformSpecificDealloc]; From 5f10f81e9436b0e5f8ef399e56085b3f6f958bb7 Mon Sep 17 00:00:00 2001 From: Marcus Westin Date: Wed, 27 Aug 2014 13:19:02 -0400 Subject: [PATCH 155/342] Use explicit `WVJB_WEBVIEW_DELEGATE_TYPE` instead of inferred `typeof(_webViewDelegate)`. Should hopefully fix GH issues #81 and #98 --- Changelog | 1 + WebViewJavascriptBridge/WebViewJavascriptBridge.m | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Changelog b/Changelog index 9553abaf..a7fb8544 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ Version History Intended v5.0.0 + Removed `WebViewJavascriptBridge -reset`. It should never have been exposed as a public API. ++ Fixed compilation in C99 mode v4.1.4 + Improve how WVJB handles the case when there is no ObjC handler for a message received from js. diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index 04ab38ee..dff06e62 100644 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -356,7 +356,7 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { _startupMessageQueue = nil; } - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { [strongDelegate webViewDidFinishLoad:webView]; } @@ -367,7 +367,7 @@ - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { _numRequestsLoading--; - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { [strongDelegate webView:webView didFailLoadWithError:error]; } @@ -376,7 +376,7 @@ - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if (webView != _webView) { return YES; } NSURL *url = [request URL]; - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { if ([[url host] isEqualToString:kQueueHasMessage]) { [self _flushMessageQueue]; @@ -396,7 +396,7 @@ - (void)webViewDidStartLoad:(UIWebView *)webView { _numRequestsLoading++; - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { [strongDelegate webViewDidStartLoad:webView]; } From f39324d731045a664c90e20926e484b0397e9bbc Mon Sep 17 00:00:00 2001 From: lokimeyburg Date: Tue, 14 Oct 2014 13:51:10 -0700 Subject: [PATCH 156/342] Added the WKWebViewJavascriptBridge class --- .../ExampleApp-iOS.xcodeproj/project.pbxproj | 6 + .../WKWebViewJavascriptBridge.h | 39 +++ .../WKWebViewJavascriptBridge.m | 317 ++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 WebViewJavascriptBridge/WKWebViewJavascriptBridge.h create mode 100644 WebViewJavascriptBridge/WKWebViewJavascriptBridge.m diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 4834adaf..43943042 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0E8082DB19EDC32300479452 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */; }; 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */; }; 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; }; 2C45CA2C1884AD520002A4E2 /* ExampleAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C45CA2B1884AD520002A4E2 /* ExampleAppViewController.m */; }; @@ -21,6 +22,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0E8082D919EDC32300479452 /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; + 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; @@ -60,6 +63,8 @@ 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */, 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */, 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */, + 0E8082D919EDC32300479452 /* WKWebViewJavascriptBridge.h */, + 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */, ); name = WebViewJavascriptBridge; path = ../../WebViewJavascriptBridge; @@ -184,6 +189,7 @@ buildActionMask = 2147483647; files = ( 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */, + 0E8082DB19EDC32300479452 /* WKWebViewJavascriptBridge.m in Sources */, 2C45CA2C1884AD520002A4E2 /* ExampleAppViewController.m in Sources */, 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h new file mode 100644 index 00000000..0082a462 --- /dev/null +++ b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h @@ -0,0 +1,39 @@ +// +// WKWebViewJavascriptBridge.h +// +// Created by Loki Meyburg on 10/15/14. +// Copyright (c) 2014 Loki Meyburg. All rights reserved. +// + +#import + +#define kCustomProtocolScheme @"wvjbscheme" +#define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" + + +#if defined(__IPHONE_8_0) + #import + #define WVJB_PLATFORM_IOS +// #define WVJB_WEBVIEW_TYPE WKWebView +// #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject +#endif + +typedef void (^WVJBResponseCallback)(id responseData); +typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); + +@interface WKWebViewJavascriptBridge : NSObject + ++ (instancetype)bridgeForWebView:(WKWebView*)webView handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)handler; ++ (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; ++ (void)enableLogging; + +- (void)send:(id)message; +- (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; +- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; +- (void)callHandler:(NSString*)handlerName; +- (void)callHandler:(NSString*)handlerName data:(id)data; +- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; +- (void)reset; + +@end \ No newline at end of file diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m new file mode 100644 index 00000000..3b877912 --- /dev/null +++ b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m @@ -0,0 +1,317 @@ +// +// WKWebViewJavascriptBridge.m +// +// Created by Loki Meyburg on 10/15/14. +// Copyright (c) 2014 Loki Meyburg. All rights reserved. +// + +#import "WKWebViewJavascriptBridge.h" + +typedef NSDictionary WVJBMessage; + +@implementation WKWebViewJavascriptBridge { + WKWebView* _webView; + id _webViewDelegate; + NSMutableArray* _startupMessageQueue; + NSMutableDictionary* _responseCallbacks; + NSMutableDictionary* _messageHandlers; + long _uniqueId; + WVJBHandler _messageHandler; + NSBundle *_resourceBundle; + NSUInteger _numRequestsLoading; +} + +/* API + *****/ + +static bool logging = false; ++ (void)enableLogging { logging = true; } + ++ (instancetype)bridgeForWebView:(WKWebView*)webView handler:(WVJBHandler)handler { + return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; +} + ++ (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)messageHandler { + return [self bridgeForWebView:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:nil]; +} + ++ (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle +{ + WKWebViewJavascriptBridge* bridge = [[WKWebViewJavascriptBridge alloc] init]; + [bridge _platformSpecificSetup:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; + [bridge reset]; + return bridge; +} + +- (void)send:(id)data { + [self send:data responseCallback:nil]; +} + +- (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { + [self _sendData:data responseCallback:responseCallback handlerName:nil]; +} + +- (void)callHandler:(NSString *)handlerName { + [self callHandler:handlerName data:nil responseCallback:nil]; +} + +- (void)callHandler:(NSString *)handlerName data:(id)data { + [self callHandler:handlerName data:data responseCallback:nil]; +} + +- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { + [self _sendData:data responseCallback:responseCallback handlerName:handlerName]; +} + +- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { + _messageHandlers[handlerName] = [handler copy]; +} + +- (void)reset { + _startupMessageQueue = [NSMutableArray array]; + _responseCallbacks = [NSMutableDictionary dictionary]; + _uniqueId = 0; +} + +/* Internals + ***********/ + +- (void)dealloc { + [self _platformSpecificDealloc]; + + _webView = nil; + _webViewDelegate = nil; + _startupMessageQueue = nil; + _responseCallbacks = nil; + _messageHandlers = nil; + _messageHandler = nil; +} + +- (void)_sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { + NSMutableDictionary* message = [NSMutableDictionary dictionary]; + + if (data) { + message[@"data"] = data; + } + + if (responseCallback) { + NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; + _responseCallbacks[callbackId] = [responseCallback copy]; + message[@"callbackId"] = callbackId; + } + + if (handlerName) { + message[@"handlerName"] = handlerName; + } + [self _queueMessage:message]; +} + +- (void)_queueMessage:(WVJBMessage*)message { + if (_startupMessageQueue) { + [_startupMessageQueue addObject:message]; + } else { + [self _dispatchMessage:message]; + } +} + +- (void)_dispatchMessage:(WVJBMessage*)message { + NSString *messageJSON = [self _serializeMessage:message]; + [self _log:@"SEND" json:messageJSON]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; + messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; + + NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; + if ([[NSThread currentThread] isMainThread]) { + [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ + [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; + }); + } +} + +- (void)_flushMessageQueue:(NSString *)messageQueueString{ + id messages = [self _deserializeMessageJSON:messageQueueString]; + if (![messages isKindOfClass:[NSArray class]]) { + NSLog(@"WKWebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messages class], messages); + return; + } + for (WVJBMessage* message in messages) { + if (![message isKindOfClass:[WVJBMessage class]]) { + NSLog(@"WKWebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); + continue; + } + [self _log:@"RCVD" json:message]; + + NSString* responseId = message[@"responseId"]; + if (responseId) { + WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; + responseCallback(message[@"responseData"]); + [_responseCallbacks removeObjectForKey:responseId]; + } else { + WVJBResponseCallback responseCallback = NULL; + NSString* callbackId = message[@"callbackId"]; + if (callbackId) { + responseCallback = ^(id responseData) { + if (responseData == nil) { + responseData = [NSNull null]; + } + + WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; + [self _queueMessage:msg]; + }; + } else { + responseCallback = ^(id ignoreResponseData) { + // Do nothing + }; + } + + WVJBHandler handler; + if (message[@"handlerName"]) { + handler = _messageHandlers[message[@"handlerName"]]; + } else { + handler = _messageHandler; + } + + if (!handler) { + [NSException raise:@"WVJBNoHandlerException" format:@"No handler for message from JS: %@", message]; + } + + handler(message[@"data"], responseCallback); + } + } +} + +- (NSString *)_serializeMessage:(id)message { + return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; +} + +- (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { + return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; +} + +- (void)_log:(NSString *)action json:(id)json { + if (!logging) { return; } + if (![json isKindOfClass:[NSString class]]) { + json = [self _serializeMessage:json]; + } + if ([json length] > 500) { + NSLog(@"WVJB %@: %@ [...]", action, [json substringToIndex:500]); + } else { + NSLog(@"WVJB %@: %@", action, json); + } +} + + + + +/* WKWebView Specific Internals + ******************************/ + +- (void) _platformSpecificSetup:(WKWebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{ + _messageHandler = messageHandler; + _webView = webView; + _webViewDelegate = webViewDelegate; + _messageHandlers = [NSMutableDictionary dictionary]; + _webView.navigationDelegate = self; + _resourceBundle = bundle; +} + +- (void) _platformSpecificDealloc { + _webView.navigationDelegate = nil; +} + + +- (void)WKFlushMessageQueue { + [_webView evaluateJavaScript:@"WebViewJavascriptBridge._fetchQueue();" completionHandler:^(NSString* result, NSError* error) { + [self _flushMessageQueue:result]; + }]; +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation +{ + if (webView != _webView) { return; } + + _numRequestsLoading--; + + if (_numRequestsLoading == 0) { + + [webView evaluateJavaScript:@"typeof WebViewJavascriptBridge == \'object\';" completionHandler:^(NSString *result, NSError *error) { + if(![result boolValue]){ + NSBundle *bundle = _resourceBundle ? _resourceBundle : [NSBundle mainBundle]; + NSString *filePath = [bundle pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; + NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + [webView evaluateJavaScript:js completionHandler:nil]; + } + }]; + } + + if (_startupMessageQueue) { + for (id queuedMessage in _startupMessageQueue) { + [self _dispatchMessage:queuedMessage]; + } + _startupMessageQueue = nil; + } + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) { + [strongDelegate webView:webView didFinishNavigation:navigation]; + } +} + + +- (void)webView:(WKWebView *)webView +decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction +decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (webView != _webView) { return; } + NSURL *url = navigationAction.request.URL; + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if ([[url scheme] isEqualToString:kCustomProtocolScheme]) { + if ([[url host] isEqualToString:kQueueHasMessage]) { + [self WKFlushMessageQueue]; + } else { + NSLog(@"WKWebViewJavascriptBridge: WARNING: Received unknown WKWebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); + } + [webView stopLoading]; + } + + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { + [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; + } +} + +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { + if (webView != _webView) { return; } + + _numRequestsLoading++; + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) { + [strongDelegate webView:webView didStartProvisionalNavigation:navigation]; + } +} + + +- (void)webView:(WKWebView *)webView +didFailNavigation:(WKNavigation *)navigation + withError:(NSError *)error { + + if (webView != _webView) { return; } + + _numRequestsLoading--; + + __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) { + [strongDelegate webView:webView didFailNavigation:navigation withError:error]; + } +} + + + +@end From b535dc2662d06a64bfd2b93739773d155248b7f3 Mon Sep 17 00:00:00 2001 From: lokimeyburg Date: Tue, 14 Oct 2014 17:17:58 -0700 Subject: [PATCH 157/342] Updated the example app to use WKWebView --- .../ExampleApp-iOS.xcodeproj/project.pbxproj | 4 ++ .../ExampleApp-iOS/ExampleAppViewController.h | 17 +++++++- .../ExampleApp-iOS/ExampleAppViewController.m | 40 ++++++++++++++----- Example Apps/ExampleApp.html | 1 + .../WKWebViewJavascriptBridge.h | 9 +---- .../WKWebViewJavascriptBridge.m | 2 + 6 files changed, 53 insertions(+), 20 deletions(-) diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 43943042..eaa1ace7 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 0E8082DB19EDC32300479452 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */; }; + 0E8082DD19EDD98700479452 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8082DC19EDD98700479452 /* WebKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 2C1562B5176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */; }; 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; }; 2C45CA2C1884AD520002A4E2 /* ExampleAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C45CA2B1884AD520002A4E2 /* ExampleAppViewController.m */; }; @@ -24,6 +25,7 @@ /* Begin PBXFileReference section */ 0E8082D919EDC32300479452 /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; + 0E8082DC19EDD98700479452 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 2C1562B4176B9F8400B4AE50 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; @@ -48,6 +50,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0E8082DD19EDD98700479452 /* WebKit.framework in Frameworks */, 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */, 2CEB3EC21602563600548120 /* Foundation.framework in Frameworks */, 2CEB3EC41602563600548120 /* CoreGraphics.framework in Frameworks */, @@ -116,6 +119,7 @@ 2CEB3EBE1602563600548120 /* Frameworks */ = { isa = PBXGroup; children = ( + 0E8082DC19EDD98700479452 /* WebKit.framework */, 2CEB3EBF1602563600548120 /* UIKit.framework */, 2CEB3EC11602563600548120 /* Foundation.framework */, 2CEB3EC31602563600548120 /* CoreGraphics.framework */, diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.h b/Example Apps/ExampleApp-iOS/ExampleAppViewController.h index d2e25c2d..96028d55 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppViewController.h +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.h @@ -8,6 +8,21 @@ #import -@interface ExampleAppViewController : UINavigationController + +#if defined(__IPHONE_8_0) + #import + #define EXAMPLE_WEBVIEW_TYPE WKWebView + #define EXAMPLE_WEBVIEW_DELEGATE_TYPE NSObject + #define EXAMPLE_WEBVIEW_DELEGATE_CONTROLLER UINavigationController + #define EXAMPLE_BRIDGE_TYPE WKWebViewJavascriptBridge +#else + #define EXAMPLE_WEBVIEW_TYPE UIWebView + #define EXAMPLE_WEBVIEW_DELEGATE_TYPE NSObject + #define EXAMPLE_WEBVIEW_DELEGATE_CONTROLLER UINavigationController + #define EXAMPLE_BRIDGE_TYPE WebViewJavascriptBridge +#endif + + +@interface ExampleAppViewController : EXAMPLE_WEBVIEW_DELEGATE_CONTROLLER @end diff --git a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m index 3f1f7794..4865326a 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppViewController.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppViewController.m @@ -7,10 +7,17 @@ // #import "ExampleAppViewController.h" + +#if defined(__IPHONE_8_0) +#import "WKWebViewJavascriptBridge.h" +# else #import "WebViewJavascriptBridge.h" +#endif @interface ExampleAppViewController () -@property WebViewJavascriptBridge* bridge; + +@property EXAMPLE_BRIDGE_TYPE* bridge; + @end @implementation ExampleAppViewController @@ -18,15 +25,26 @@ @implementation ExampleAppViewController - (void)viewWillAppear:(BOOL)animated { if (_bridge) { return; } - UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; - [self.view addSubview:webView]; + #if defined(__IPHONE_8_0) + WKWebView* webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; + webView.navigationDelegate = self; + [self.view addSubview:webView]; + [WKWebViewJavascriptBridge enableLogging]; + _bridge = [WKWebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"ObjC received message from JS: %@", data); + responseCallback(@"Response for message from ObjC"); + }]; + #else + UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; + [self.view addSubview:webView]; + [WebViewJavascriptBridge enableLogging]; + _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { + NSLog(@"ObjC received message from JS: %@", data); + responseCallback(@"Response for message from ObjC"); + }]; + #endif - [WebViewJavascriptBridge enableLogging]; - - _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"ObjC received message from JS: %@", data); - responseCallback(@"Response for message from ObjC"); - }]; + [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"testObjcCallback called: %@", data); @@ -53,7 +71,7 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"webViewDidFinishLoad"); } -- (void)renderButtons:(UIWebView*)webView { +- (void)renderButtons:(EXAMPLE_WEBVIEW_TYPE*)webView { UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; UIButton *messageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; @@ -92,7 +110,7 @@ - (void)callHandler:(id)sender { }]; } -- (void)loadExamplePage:(UIWebView*)webView { +- (void)loadExamplePage:(EXAMPLE_WEBVIEW_TYPE*)webView { NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; diff --git a/Example Apps/ExampleApp.html b/Example Apps/ExampleApp.html index d31f1fb1..4278a8ad 100644 --- a/Example Apps/ExampleApp.html +++ b/Example Apps/ExampleApp.html @@ -1,5 +1,6 @@ +