diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h index 4e3404fc..3b94597a 100644 --- a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h @@ -17,6 +17,8 @@ @interface WKWebViewJavascriptBridge : NSObject +@property (weak, nonatomic) id webViewDelegate; + + (instancetype)bridgeForWebView:(WKWebView*)webView; + (void)enableLogging; @@ -26,7 +28,6 @@ - (void)callHandler:(NSString*)handlerName data:(id)data; - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; - (void)reset; -- (void)setWebViewDelegate:(id)webViewDelegate; - (void)disableJavscriptAlertBoxSafetyTimeout; @end diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m index 47667df6..c123e27a 100644 --- a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m @@ -10,12 +10,14 @@ #if defined supportsWKWebView -@implementation WKWebViewJavascriptBridge { - __weak WKWebView* _webView; - __weak id _webViewDelegate; - long _uniqueId; - WebViewJavascriptBridgeBase *_base; -} +@interface WKWebViewJavascriptBridge () + +@property (strong, nonatomic) WKWebView *webView; +@property (strong, nonatomic) WebViewJavascriptBridgeBase *base; + +@end + +@implementation WKWebViewJavascriptBridge /* API *****/ @@ -34,7 +36,7 @@ - (void)send:(id)data { } - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [_base sendData:data responseCallback:responseCallback handlerName:nil]; + [self.base sendData:data responseCallback:responseCallback handlerName:nil]; } - (void)callHandler:(NSString *)handlerName { @@ -46,11 +48,11 @@ - (void)callHandler:(NSString *)handlerName data:(id)data { } - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; + [self.base sendData:data responseCallback:responseCallback handlerName:handlerName]; } - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - _base.messageHandlers[handlerName] = [handler copy]; + self.base.messageHandlers[handlerName] = [handler copy]; } - (void)removeHandler:(NSString *)handlerName { @@ -58,25 +60,11 @@ - (void)removeHandler:(NSString *)handlerName { } - (void)reset { - [_base reset]; -} - -- (void)setWebViewDelegate:(id)webViewDelegate { - _webViewDelegate = webViewDelegate; + [self.base reset]; } - (void)disableJavscriptAlertBoxSafetyTimeout { - [_base disableJavscriptAlertBoxSafetyTimeout]; -} - -/* Internals - ***********/ - -- (void)dealloc { - _base = nil; - _webView = nil; - _webViewDelegate = nil; - _webView.navigationDelegate = nil; + [self.base disableJavscriptAlertBoxSafetyTimeout]; } @@ -92,105 +80,96 @@ - (void) _setupInstance:(WKWebView*)webView { - (void)WKFlushMessageQueue { - [_webView evaluateJavaScript:[_base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) { + [self.webView evaluateJavaScript:[self.base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) { if (error != nil) { NSLog(@"WebViewJavascriptBridge: WARNING: Error when trying to fetch data from WKWebView: %@", error); } - [_base flushMessageQueue:result]; + [self.base flushMessageQueue:result]; }]; } -- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) { - [strongDelegate webView:webView didFinishNavigation:navigation]; +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation +{ + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) { + [self.webViewDelegate webView:webView didFinishNavigation:navigation]; } } -- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationResponse:decisionHandler:)]) { - [strongDelegate webView:webView decidePolicyForNavigationResponse:navigationResponse decisionHandler:decisionHandler]; +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler +{ + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationResponse:decisionHandler:)]) { + [self.webViewDelegate webView:webView decidePolicyForNavigationResponse:navigationResponse decisionHandler:decisionHandler]; + return; } - else { + + if (decisionHandler) { decisionHandler(WKNavigationResponsePolicyAllow); } } -- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didReceiveAuthenticationChallenge:completionHandler:)]) { - [strongDelegate webView:webView didReceiveAuthenticationChallenge:challenge completionHandler:completionHandler]; - } else { +- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler +{ + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didReceiveAuthenticationChallenge:completionHandler:)]) { + [self.webViewDelegate webView:webView didReceiveAuthenticationChallenge:challenge completionHandler:completionHandler]; + return; + } + + if (completionHandler) { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } - (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 ([_base isWebViewJavascriptBridgeURL:url]) { - if ([_base isBridgeLoadedURL:url]) { - [_base injectJavascriptFile]; - } else if ([_base isQueueMessageURL:url]) { + if ([self.base isCorrectProcotocolScheme:url]) { + if ([self.base isBridgeLoadedURL:url]) { + [self.base injectJavascriptFile]; + } else if ([self.base isQueueMessageURL:url]) { [self WKFlushMessageQueue]; } else { - [_base logUnkownMessage:url]; + [self.base logUnkownMessage:url]; + } + if (decisionHandler) { + decisionHandler(WKNavigationActionPolicyCancel); } - decisionHandler(WKNavigationActionPolicyCancel); } - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { - [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; - } else { + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { + [self.webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; + return; + } + + if (decisionHandler) { decisionHandler(WKNavigationActionPolicyAllow); } } - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) { - [strongDelegate webView:webView didStartProvisionalNavigation:navigation]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) { + [self.webViewDelegate webView:webView didStartProvisionalNavigation:navigation]; } } - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) { - [strongDelegate webView:webView didFailNavigation:navigation withError:error]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) { + [self.webViewDelegate webView:webView didFailNavigation:navigation withError:error]; } } - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { - if (webView != _webView) { return; } - - __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)]) { - [strongDelegate webView:webView didFailProvisionalNavigation:navigation withError:error]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)]) { + [self.webViewDelegate webView:webView didFailProvisionalNavigation:navigation withError:error]; } } -- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { - [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; - return NULL; +- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand +{ + [self.webView evaluateJavaScript:javascriptCommand completionHandler:nil]; + return nil; } - - @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h index 1b64bb4e..416fc2aa 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -32,6 +32,7 @@ @interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_INTERFACE +@property (weak, nonatomic) WVJB_WEBVIEW_DELEGATE_TYPE *webViewDelegate; + (instancetype)bridgeForWebView:(id)webView; + (instancetype)bridge:(id)webView; @@ -44,7 +45,6 @@ - (void)callHandler:(NSString*)handlerName; - (void)callHandler:(NSString*)handlerName data:(id)data; - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; -- (void)setWebViewDelegate:(id)webViewDelegate; - (void)disableJavscriptAlertBoxSafetyTimeout; @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m index e74a6e24..dbc90494 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -8,22 +8,14 @@ #import "WebViewJavascriptBridge.h" -#if defined(supportsWKWebView) -#import "WKWebViewJavascriptBridge.h" -#endif +@interface WebViewJavascriptBridge () -#if __has_feature(objc_arc_weak) - #define WVJB_WEAK __weak -#else - #define WVJB_WEAK __unsafe_unretained -#endif +@property (strong, nonatomic) WVJB_WEBVIEW_TYPE *webView; +@property (strong, nonatomic) WebViewJavascriptBridgeBase *base; -@implementation WebViewJavascriptBridge { - WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView; - WVJB_WEAK id _webViewDelegate; - long _uniqueId; - WebViewJavascriptBridgeBase *_base; -} +@end + +@implementation WebViewJavascriptBridge /* API *****/ @@ -31,6 +23,7 @@ @implementation WebViewJavascriptBridge { + (void)enableLogging { [WebViewJavascriptBridgeBase enableLogging]; } + + (void)setLogMaxLength:(int)length { [WebViewJavascriptBridgeBase setLogMaxLength:length]; } @@ -53,16 +46,12 @@ + (instancetype)bridge:(id)webView { return nil; } -- (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate { - _webViewDelegate = webViewDelegate; -} - - (void)send:(id)data { [self send:data responseCallback:nil]; } - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [_base sendData:data responseCallback:responseCallback handlerName:nil]; + [self.base sendData:data responseCallback:responseCallback handlerName:nil]; } - (void)callHandler:(NSString *)handlerName { @@ -74,11 +63,11 @@ - (void)callHandler:(NSString *)handlerName data:(id)data { } - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; + [self.base sendData:data responseCallback:responseCallback handlerName:handlerName]; } - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - _base.messageHandlers[handlerName] = [handler copy]; + self.base.messageHandlers[handlerName] = [handler copy]; } - (void)removeHandler:(NSString *)handlerName { @@ -86,22 +75,16 @@ - (void)removeHandler:(NSString *)handlerName { } - (void)disableJavscriptAlertBoxSafetyTimeout { - [_base disableJavscriptAlertBoxSafetyTimeout]; + [self.base disableJavscriptAlertBoxSafetyTimeout]; } /* Platform agnostic internals *****************************/ -- (void)dealloc { - [self _platformSpecificDealloc]; - _base = nil; - _webView = nil; - _webViewDelegate = nil; -} - -- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { - return [_webView stringByEvaluatingJavaScriptFromString:javascriptCommand]; +- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand +{ + return [self.webView stringByEvaluatingJavaScriptFromString:javascriptCommand]; } #if defined WVJB_PLATFORM_OSX @@ -115,26 +98,25 @@ - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { _base.delegate = self; } -- (void) _platformSpecificDealloc { - _webView.policyDelegate = nil; -} -- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { - if (webView != _webView) { return; } - +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener +{ + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { + [self.webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; { + return; + } + NSURL *url = [request URL]; - if ([_base isWebViewJavascriptBridgeURL:url]) { - if ([_base isBridgeLoadedURL:url]) { - [_base injectJavascriptFile]; - } else if ([_base isQueueMessageURL:url]) { - NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; - [_base flushMessageQueue:messageQueueString]; + if ([self.base isCorrectProcotocolScheme:url]) { + if ([self.base isBridgeLoadedURL:url]) { + [self.base injectJavascriptFile]; + } else if ([self.base isQueueMessageURL:url]) { + NSString *messageQueueString = [self _evaluateJavascript:[self.base webViewJavascriptFetchQueyCommand]]; + [self.base flushMessageQueue:messageQueueString]; } else { - [_base logUnkownMessage:url]; + [self.base logUnkownMessage:url]; } [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]; } @@ -153,56 +135,44 @@ - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { _base.delegate = self; } -- (void) _platformSpecificDealloc { - _webView.delegate = nil; -} - - (void)webViewDidFinishLoad:(UIWebView *)webView { - if (webView != _webView) { return; } - - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { - [strongDelegate webViewDidFinishLoad:webView]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { + [self.webViewDelegate webViewDidFinishLoad:webView]; } } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { - if (webView != _webView) { return; } - - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { - [strongDelegate webView:webView didFailLoadWithError:error]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + [self.webViewDelegate webView:webView didFailLoadWithError:error]; } } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { - if (webView != _webView) { return YES; } + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { + return [self.webViewDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; + } NSURL *url = [request URL]; - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if ([_base isWebViewJavascriptBridgeURL:url]) { - if ([_base isBridgeLoadedURL:url]) { - [_base injectJavascriptFile]; - } else if ([_base isQueueMessageURL:url]) { - NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; - [_base flushMessageQueue:messageQueueString]; + + if ([self.base isCorrectProcotocolScheme:url]) { + + if ([self.base isBridgeLoadedURL:url]) { + [self.base injectJavascriptFile]; + } else if ([self.base isQueueMessageURL:url]) { + NSString *messageQueueString = [self _evaluateJavascript:[self.base webViewJavascriptFetchQueyCommand]]; + [self.base flushMessageQueue:messageQueueString]; } else { - [_base logUnkownMessage:url]; + [self.base logUnkownMessage:url]; } return NO; - } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { - return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; - } else { - return YES; } + + return YES; } - (void)webViewDidStartLoad:(UIWebView *)webView { - if (webView != _webView) { return; } - - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { - [strongDelegate webViewDidStartLoad:webView]; + if (self.webViewDelegate && [self.webViewDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { + [self.webViewDelegate webViewDidStartLoad:webView]; } } diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m index 3ec26ed4..921f99b4 100755 --- a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m @@ -10,7 +10,6 @@ #import "WebViewJavascriptBridge_JS.h" @implementation WebViewJavascriptBridgeBase { - __weak id _webViewDelegate; long _uniqueId; } @@ -20,22 +19,17 @@ @implementation WebViewJavascriptBridgeBase { + (void)enableLogging { logging = true; } + (void)setLogMaxLength:(int)length { logMaxLength = length;} -- (id)init { +- (instancetype)init { if (self = [super init]) { - self.messageHandlers = [NSMutableDictionary dictionary]; - self.startupMessageQueue = [NSMutableArray array]; - self.responseCallbacks = [NSMutableDictionary dictionary]; + _messageHandlers = [NSMutableDictionary dictionary]; + _startupMessageQueue = [NSMutableArray array]; + _responseCallbacks = [NSMutableDictionary dictionary]; _uniqueId = 0; } + return self; } -- (void)dealloc { - self.startupMessageQueue = nil; - self.responseCallbacks = nil; - self.messageHandlers = nil; -} - - (void)reset { self.startupMessageQueue = [NSMutableArray array]; self.responseCallbacks = [NSMutableDictionary dictionary]; @@ -61,7 +55,7 @@ - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallbac [self _queueMessage:message]; } -- (void)flushMessageQueue:(NSString *)messageQueueString{ +- (void)flushMessageQueue:(NSString *)messageQueueString { if (messageQueueString == nil || messageQueueString.length == 0) { NSLog(@"WebViewJavascriptBridge: WARNING: ObjC got nil while fetching the message queue JSON from webview. This can happen if the WebViewJavascriptBridge JS is not currently present in the webview, e.g if the webview just loaded a new page."); return; @@ -81,7 +75,8 @@ - (void)flushMessageQueue:(NSString *)messageQueueString{ responseCallback(message[@"responseData"]); [self.responseCallbacks removeObjectForKey:responseId]; } else { - WVJBResponseCallback responseCallback = NULL; + WVJBResponseCallback responseCallback = ^(id ignoreResponseData) {}; + NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { @@ -92,10 +87,6 @@ - (void)flushMessageQueue:(NSString *)messageQueueString{ WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; [self _queueMessage:msg]; }; - } else { - responseCallback = ^(id ignoreResponseData) { - // Do nothing - }; } WVJBHandler handler = self.messageHandlers[message[@"handlerName"]]; @@ -114,7 +105,7 @@ - (void)injectJavascriptFile { NSString *js = WebViewJavascriptBridge_js(); [self _evaluateJavascript:js]; if (self.startupMessageQueue) { - NSArray* queue = self.startupMessageQueue; + NSArray* queue = [self.startupMessageQueue copy]; self.startupMessageQueue = nil; for (id queuedMessage in queue) { [self _dispatchMessage:queuedMessage]; @@ -164,7 +155,9 @@ - (void)disableJavscriptAlertBoxSafetyTimeout { // ------------------------------------------- - (void) _evaluateJavascript:(NSString *)javascriptCommand { - [self.delegate _evaluateJavascript:javascriptCommand]; + if (self.delegate) { + [self.delegate _evaluateJavascript:javascriptCommand]; + } } - (void)_queueMessage:(WVJBMessage*)message {