diff --git a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj index d08ca0ab..53d6c361 100644 --- a/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj @@ -7,8 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 0ECB01491A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ECB01461A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.m */; }; - 0ECB014A1A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ECB01481A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.m */; }; 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 */; }; @@ -16,16 +14,11 @@ 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; }; 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; }; 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; }; - 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */; }; - 2C3E7C491C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C481C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.m */; }; 2CF17F5317D8AACF006E828B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CF17F5217D8AACF006E828B /* MainMenu.xib */; }; + EF5DC17623474A0A00F81F96 /* WKWebView+JavaScriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 0ECB01451A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; - 0ECB01461A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; - 0ECB01471A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; - 0ECB01481A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; 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; }; @@ -40,11 +33,9 @@ 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; }; 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 = ""; }; - 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; - 2C3E7C471C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_JS.h; sourceTree = ""; }; - 2C3E7C481C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_JS.m; sourceTree = ""; }; 2CF17F5217D8AACF006E828B /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + EF5DC17423474A0A00F81F96 /* WKWebView+JavaScriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WKWebView+JavaScriptBridge.h"; sourceTree = ""; }; + EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WKWebView+JavaScriptBridge.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -125,14 +116,8 @@ 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 2C3E7C471C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.h */, - 2C3E7C481C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.m */, - 0ECB01451A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.h */, - 0ECB01461A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.m */, - 0ECB01471A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.h */, - 0ECB01481A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.m */, - 2C1562C2176BA9FF00B4AE50 /* WebViewJavascriptBridge.h */, - 2C1562C4176BA9FF00B4AE50 /* WebViewJavascriptBridge.m */, + EF5DC17423474A0A00F81F96 /* WKWebView+JavaScriptBridge.h */, + EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */, ); name = WebViewJavascriptBridge; path = ../../WebViewJavascriptBridge; @@ -172,6 +157,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 2C136A1817641106004C7401; @@ -203,11 +189,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0ECB01491A0EEB3A0037FF4E /* WebViewJavascriptBridgeBase.m in Sources */, - 0ECB014A1A0EEB3A0037FF4E /* WKWebViewJavascriptBridge.m in Sources */, - 2C3E7C491C5A8B8D00A1E322 /* WebViewJavascriptBridge_JS.m in Sources */, + EF5DC17623474A0A00F81F96 /* WKWebView+JavaScriptBridge.m in Sources */, 2C136A3117641106004C7401 /* main.m in Sources */, - 2C1562C6176BA9FF00B4AE50 /* WebViewJavascriptBridge.m in Sources */, 2C136A3817641106004C7401 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example Apps/ExampleApp-OSX/AppDelegate.m b/Example Apps/ExampleApp-OSX/AppDelegate.m index 5677342a..46df6bae 100644 --- a/Example Apps/ExampleApp-OSX/AppDelegate.m +++ b/Example Apps/ExampleApp-OSX/AppDelegate.m @@ -8,69 +8,27 @@ #import "AppDelegate.h" #import -#import "WebViewJavascriptBridge.h" +#import "WKWebView+JavaScriptBridge.h" @implementation AppDelegate { - WebView* _webView; WKWebView *_WKWebView; - WebViewJavascriptBridge* _bridge; - WebViewJavascriptBridge* _WKBridge; NSView* _WKWebViewWrapper; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [self _createViews]; - [self _configureWebview]; [self _configureWKWebview]; } -- (void)_configureWebview { - // Create Bridge - _bridge = [WebViewJavascriptBridge bridgeForWebView:_webView]; - - [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"testObjcCallback called: %@", data); - responseCallback(@"Response from testObjcCallback"); - }]; - - [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; - - // Create Buttons - NSButton *callbackButton = [[NSButton alloc] initWithFrame:NSMakeRect(5, 0, 120, 40)]; - [callbackButton setTitle:@"Call handler"]; - [callbackButton setBezelStyle:NSRoundedBezelStyle]; - [callbackButton setTarget:self]; - [callbackButton setAction:@selector(_callHandler)]; - [_webView addSubview:callbackButton]; - - NSButton *webViewToggleButton = [[NSButton alloc] initWithFrame:NSMakeRect(120, 0, 180, 40)]; - [webViewToggleButton setTitle:@"Switch to WKWebView"]; - [webViewToggleButton setBezelStyle:NSRoundedBezelStyle]; - [webViewToggleButton setTarget:self]; - [webViewToggleButton setAction:@selector(_toggleExample)]; - [_webView addSubview:webViewToggleButton]; - - - // Load Page - NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; - NSString* html = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; - NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; - [[_webView mainFrame] loadHTMLString:html baseURL: baseURL]; -} - - - (void)_configureWKWebview { // Create Bridge - _WKBridge = [WebViewJavascriptBridge bridgeForWebView:_WKWebView]; - - [_WKBridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { + [WKWebView enableLogging:LogginglevelAll]; + [_WKWebView registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"testObjcCallback called: %@", data); responseCallback(@"Response from testObjcCallback"); }]; - [_WKBridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; - // Create Buttons NSButton *callbackButton = [[NSButton alloc] initWithFrame:NSMakeRect(5, 0, 120, 40)]; [callbackButton setTitle:@"Call handler"]; @@ -79,12 +37,6 @@ - (void)_configureWKWebview { [callbackButton setAction:@selector(_WKCallHandler)]; [_WKWebView addSubview:callbackButton]; - NSButton *webViewToggleButton = [[NSButton alloc] initWithFrame:NSMakeRect(120, 0, 180, 40)]; - [webViewToggleButton setTitle:@"Switch to WebView"]; - [webViewToggleButton setBezelStyle:NSRoundedBezelStyle]; - [webViewToggleButton setTarget:self]; - [webViewToggleButton setAction:@selector(_toggleExample)]; - [_WKWebView addSubview:webViewToggleButton]; // Load Page NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; @@ -92,39 +44,21 @@ - (void)_configureWKWebview { NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; [_WKWebView loadHTMLString:html baseURL:baseURL]; } - --(void)_toggleExample { - _WKWebView.hidden = !_WKWebView.isHidden; - _webView.hidden = !_webView.isHidden; -} - -- (void)_callHandler { - id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; - [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { - NSLog(@"testJavascriptHandler responded: %@", response); - }]; -} - - (void)_WKCallHandler { id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; - [_WKBridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { + [_WKWebView callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { NSLog(@"testJavascriptHandler responded: %@", response); }]; } - (void)_createViews { NSView* contentView = _window.contentView; - // WebView - _webView = [[WebView alloc] initWithFrame:contentView.frame]; - [_webView setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; - _webView.hidden = YES; - // WKWebView - _WKWebView = [[WKWebView alloc] initWithFrame:contentView.frame]; + WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; + _WKWebView = [[WKWebView alloc] initWithFrame:contentView.frame configuration:config]; [_WKWebView setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; [contentView addSubview:_WKWebView]; - [contentView addSubview:_webView]; } diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj index 324a5b06..5f180388 100644 --- a/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj +++ b/Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj @@ -8,34 +8,24 @@ /* Begin PBXBuildFile section */ 0E4E9D4C1A101E0B00043087 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8082DC19EDD98700479452 /* WebKit.framework */; }; - 0E50601C1A01B442000BEEEA /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E50601B1A01B442000BEEEA /* WebViewJavascriptBridgeBase.m */; }; - 0E8082DB19EDC32300479452 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */; }; 0ECB01441A0EE1F20037FF4E /* ExampleWKWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */; }; - 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */; }; - 2C3E7C461C5A890A00A1E322 /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C451C5A890A00A1E322 /* WebViewJavascriptBridge_JS.m */; }; - 2C45CA2C1884AD520002A4E2 /* ExampleUIWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C45CA2B1884AD520002A4E2 /* ExampleUIWebViewController.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 */; }; 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 */; }; + EF5D0B3224599757008DC69C /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */; }; + EF5D0B3324599757008DC69C /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */; }; + EF5D0B3424599757008DC69C /* WebViewJavascriptLeakAvoider.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */; }; + EFE398AF242C348C0027857D /* TestConsole.html in Resources */ = {isa = PBXBuildFile; fileRef = EFE398AE242C348C0027857D /* TestConsole.html */; }; + EFF05EC5244C0FED0060F71C /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EFF05EC4244C0FED0060F71C /* FirstViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 0E50601B1A01B442000BEEEA /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; - 0E50601D1A01B44C000BEEEA /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; - 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; }; 0ECB01421A0EE1BA0037FF4E /* ExampleWKWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleWKWebViewController.h; sourceTree = ""; }; 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleWKWebViewController.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 = ""; }; - 2C3E7C441C5A890A00A1E322 /* WebViewJavascriptBridge_JS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_JS.h; sourceTree = ""; }; - 2C3E7C451C5A890A00A1E322 /* WebViewJavascriptBridge_JS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_JS.m; sourceTree = ""; }; - 2C45CA2A1884AD520002A4E2 /* ExampleUIWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleUIWebViewController.h; sourceTree = ""; }; - 2C45CA2B1884AD520002A4E2 /* ExampleUIWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleUIWebViewController.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 = ""; }; @@ -48,6 +38,15 @@ 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; }; + EF5D0B2C24599756008DC69C /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; + EF5D0B2D24599756008DC69C /* WebViewJavascriptLeakAvoider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptLeakAvoider.h; sourceTree = ""; }; + EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; + EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; + EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptLeakAvoider.m; sourceTree = ""; }; + EF5D0B3124599757008DC69C /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; + EFE398AE242C348C0027857D /* TestConsole.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = TestConsole.html; sourceTree = SOURCE_ROOT; }; + EFF05EC3244C0FED0060F71C /* FirstViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = ""; }; + EFF05EC4244C0FED0060F71C /* FirstViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,14 +65,12 @@ 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */ = { isa = PBXGroup; children = ( - 2C3E7C441C5A890A00A1E322 /* WebViewJavascriptBridge_JS.h */, - 2C3E7C451C5A890A00A1E322 /* WebViewJavascriptBridge_JS.m */, - 2C1562A8176B9F6200B4AE50 /* WebViewJavascriptBridge.h */, - 2C1562A9176B9F6200B4AE50 /* WebViewJavascriptBridge.m */, - 0E8082DA19EDC32300479452 /* WKWebViewJavascriptBridge.m */, - 0E8082D919EDC32300479452 /* WKWebViewJavascriptBridge.h */, - 0E50601B1A01B442000BEEEA /* WebViewJavascriptBridgeBase.m */, - 0E50601D1A01B44C000BEEEA /* WebViewJavascriptBridgeBase.h */, + EF5D0B2C24599756008DC69C /* WebViewJavascriptBridge.h */, + EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */, + EF5D0B3124599757008DC69C /* WebViewJavascriptBridgeBase.h */, + EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */, + EF5D0B2D24599756008DC69C /* WebViewJavascriptLeakAvoider.h */, + EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */, ); name = WebViewJavascriptBridge; path = ../../WebViewJavascriptBridge; @@ -83,10 +80,11 @@ isa = PBXGroup; children = ( 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, + EFE398AE242C348C0027857D /* TestConsole.html */, 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, - 2C45CA2A1884AD520002A4E2 /* ExampleUIWebViewController.h */, - 2C45CA2B1884AD520002A4E2 /* ExampleUIWebViewController.m */, + EFF05EC3244C0FED0060F71C /* FirstViewController.h */, + EFF05EC4244C0FED0060F71C /* FirstViewController.m */, 0ECB01421A0EE1BA0037FF4E /* ExampleWKWebViewController.h */, 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */, 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */, @@ -173,6 +171,7 @@ ORGANIZATIONNAME = "Marcus Westin"; TargetAttributes = { 2CEB3EBA1602563600548120 = { + DevelopmentTeam = D9DMY5ZV46; LastSwiftMigration = 0820; }; }; @@ -182,6 +181,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 2CEB3EB01602563600548120; @@ -201,6 +201,7 @@ files = ( 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */, 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */, + EFE398AF242C348C0027857D /* TestConsole.html in Resources */, 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -212,14 +213,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2C3E7C461C5A890A00A1E322 /* WebViewJavascriptBridge_JS.m in Sources */, - 2C1562C0176BA63500B4AE50 /* WebViewJavascriptBridge.m in Sources */, - 0E8082DB19EDC32300479452 /* WKWebViewJavascriptBridge.m in Sources */, - 2C45CA2C1884AD520002A4E2 /* ExampleUIWebViewController.m in Sources */, 0ECB01441A0EE1F20037FF4E /* ExampleWKWebViewController.m in Sources */, + EFF05EC5244C0FED0060F71C /* FirstViewController.m in Sources */, + EF5D0B3424599757008DC69C /* WebViewJavascriptLeakAvoider.m in Sources */, 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, - 0E50601C1A01B442000BEEEA /* WebViewJavascriptBridgeBase.m in Sources */, 2CA045C317117439006DEE8B /* main.m in Sources */, + EF5D0B3324599757008DC69C /* WebViewJavascriptBridgeBase.m in Sources */, + EF5D0B3224599757008DC69C /* WebViewJavascriptBridge.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -316,6 +316,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = D9DMY5ZV46; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch"; INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist"; @@ -333,6 +334,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = D9DMY5ZV46; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch"; INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist"; diff --git a/Example Apps/ExampleApp-iOS.xcodeproj/xcshareddata/xcschemes/ExampleApp-iOS.xcscheme b/Example Apps/ExampleApp-iOS.xcodeproj/xcshareddata/xcschemes/ExampleApp-iOS.xcscheme new file mode 100644 index 00000000..a902b6a7 --- /dev/null +++ b/Example Apps/ExampleApp-iOS.xcodeproj/xcshareddata/xcschemes/ExampleApp-iOS.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m index ff9f5bef..c083d00f 100644 --- a/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m +++ b/Example Apps/ExampleApp-iOS/ExampleAppDelegate.m @@ -1,29 +1,23 @@ #import "ExampleAppDelegate.h" -#import "ExampleUIWebViewController.h" #import "ExampleWKWebViewController.h" +#import "FirstViewController.h" @implementation ExampleAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // 1. Create the UIWebView example - ExampleUIWebViewController* UIWebViewExampleController = [[ExampleUIWebViewController alloc] init]; - UIWebViewExampleController.tabBarItem.title = @"UIWebView"; - - // 2. Create the tab footer and add the UIWebView example UITabBarController *tabBarController = [[UITabBarController alloc] init]; - [tabBarController addChildViewController:UIWebViewExampleController]; - // 3. Create the WKWebView example for devices >= iOS 8 - if([WKWebView class]) { - ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; - WKWebViewExampleController.tabBarItem.title = @"WKWebView"; - [tabBarController addChildViewController:WKWebViewExampleController]; - } + ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; + WKWebViewExampleController.tabBarItem.title = @"WKWebView"; + [tabBarController addChildViewController:WKWebViewExampleController]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.rootViewController = tabBarController; + + UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[FirstViewController new]]; + self.window.rootViewController = nav; [self.window makeKeyAndVisible]; + return YES; } diff --git a/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.h b/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.h deleted file mode 100644 index 71364e80..00000000 --- a/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// ExampleUIWebViewController.h -// ExampleApp-iOS -// -// Created by Marcus Westin on 1/13/14. -// Copyright (c) 2014 Marcus Westin. All rights reserved. -// - -#import - -@interface ExampleUIWebViewController : UINavigationController - -@end \ No newline at end of file diff --git a/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.m b/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.m deleted file mode 100644 index f988a014..00000000 --- a/Example Apps/ExampleApp-iOS/ExampleUIWebViewController.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// ExampleUIWebViewController.m -// ExampleApp-iOS -// -// Created by Marcus Westin on 1/13/14. -// Copyright (c) 2014 Marcus Westin. All rights reserved. -// - -#import "ExampleUIWebViewController.h" -#import "WebViewJavascriptBridge.h" - -@interface ExampleUIWebViewController () -@property WebViewJavascriptBridge* bridge; -@end - -@implementation ExampleUIWebViewController - -- (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]; - [_bridge setWebViewDelegate:self]; - - [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"testObjcCallback called: %@", data); - responseCallback(@"Response from testObjcCallback"); - }]; - - [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; - - [self renderButtons:webView]; - [self loadExamplePage:webView]; -} - -- (void)webViewDidStartLoad:(UIWebView *)webView { - NSLog(@"webViewDidStartLoad"); -} - -- (void)webViewDidFinishLoad:(UIWebView *)webView { - NSLog(@"webViewDidFinishLoad"); -} - -- (void)renderButtons:(UIWebView*)webView { - UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:11.0]; - - 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(0, 400, 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(90, 400, 100, 35); - reloadButton.titleLabel.font = font; - - UIButton* safetyTimeoutButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [safetyTimeoutButton setTitle:@"Disable safety timeout" forState:UIControlStateNormal]; - [safetyTimeoutButton addTarget:self action:@selector(disableSafetyTimeout) forControlEvents:UIControlEventTouchUpInside]; - [self.view insertSubview:safetyTimeoutButton aboveSubview:webView]; - safetyTimeoutButton.frame = CGRectMake(190, 400, 120, 35); - safetyTimeoutButton.titleLabel.font = font; -} - -- (void)disableSafetyTimeout { - [self.bridge disableJavscriptAlertBoxSafetyTimeout]; -} - -- (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]; - NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; - [webView loadHTMLString:appHtml baseURL:baseURL]; -} -@end diff --git a/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.h b/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.h index 7dd92b8e..14b8cf9b 100644 --- a/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.h +++ b/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.h @@ -9,6 +9,6 @@ #import #import -@interface ExampleWKWebViewController : UINavigationController +@interface ExampleWKWebViewController : UIViewController -@end \ No newline at end of file +@end diff --git a/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m b/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m index f9d4ac79..f7ca6df5 100644 --- a/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m +++ b/Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m @@ -8,42 +8,30 @@ #import "ExampleWKWebViewController.h" #import "WebViewJavascriptBridge.h" - @interface ExampleWKWebViewController () - -@property WebViewJavascriptBridge* bridge; - +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, strong) WebViewJavascriptBridge* bridge; @end @implementation ExampleWKWebViewController -- (void)viewWillAppear:(BOOL)animated { - if (_bridge) { return; } +- (void)viewDidLoad { + [super viewDidLoad]; - WKWebView* webView = [[NSClassFromString(@"WKWebView") alloc] initWithFrame:self.view.bounds]; - webView.navigationDelegate = self; - [self.view addSubview:webView]; - [WebViewJavascriptBridge enableLogging]; - _bridge = [WebViewJavascriptBridge bridgeForWebView:webView]; - [_bridge setWebViewDelegate:self]; + self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; + [self.view addSubview:self.webView]; + _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView + showJSconsole:YES + enableLogging:YES]; + [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"testObjcCallback called: %@", data); - responseCallback(@"Response from testObjcCallback"); + responseCallback(@"Response from testObjcCallback111"); }]; + [self renderButtons:self.webView]; + [self loadExamplePage:self.webView]; - [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }]; - - [self renderButtons:webView]; - [self loadExamplePage:webView]; -} - -- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { - NSLog(@"webViewDidStartLoad"); -} - -- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { - NSLog(@"webViewDidFinishLoad"); } - (void)renderButtons:(WKWebView*)webView { @@ -62,6 +50,7 @@ - (void)renderButtons:(WKWebView*)webView { [self.view insertSubview:reloadButton aboveSubview:webView]; reloadButton.frame = CGRectMake(110, 400, 100, 35); reloadButton.titleLabel.font = font; + } - (void)callHandler:(id)sender { @@ -77,4 +66,20 @@ - (void)loadExamplePage:(WKWebView*)webView { NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; [webView loadHTMLString:appHtml baseURL:baseURL]; } +- (WKWebView *) webView { + if (!_webView) { + WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; + _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; + [self.view addSubview:_webView]; + + } + return _webView; +} + +-(void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + + NSLog(@"viewDidDisappear``"); + [self.webView.configuration.userContentController removeAllUserScripts]; +} @end diff --git a/Example Apps/ExampleApp-iOS/FirstViewController.h b/Example Apps/ExampleApp-iOS/FirstViewController.h new file mode 100644 index 00000000..ecec350d --- /dev/null +++ b/Example Apps/ExampleApp-iOS/FirstViewController.h @@ -0,0 +1,16 @@ +// +// FirstViewController.h +// ExampleApp-iOS +// +// Created by 侯森魁 on 2020/4/19. +// Copyright © 2020 Marcus Westin. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FirstViewController : UIViewController +@end + +NS_ASSUME_NONNULL_END diff --git a/Example Apps/ExampleApp-iOS/FirstViewController.m b/Example Apps/ExampleApp-iOS/FirstViewController.m new file mode 100644 index 00000000..f2313109 --- /dev/null +++ b/Example Apps/ExampleApp-iOS/FirstViewController.m @@ -0,0 +1,49 @@ +// +// FirstViewController.m +// ExampleApp-iOS +// +// Created by 侯森魁 on 2020/4/19. +// Copyright © 2020 Marcus Westin. All rights reserved. +// + +#import "FirstViewController.h" +#import "ExampleWKWebViewController.h" +@interface FirstViewController () + +@end + +@implementation FirstViewController + + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = @"first page"; + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + [button setTitle:@"click me" forState:UIControlStateNormal]; + [button addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside]; + button.frame = CGRectMake(100, 200, 100, 40); + button.center = self.view.center; + self.view.backgroundColor = [UIColor redColor]; + [self.view addSubview:button]; + // Do any additional setup after loading the view. +} +- (void)jump{ +// UITabBarController *tabBarController = [[UITabBarController alloc] init]; + + ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; +// WKWebViewExampleController.tabBarItem.title = @"WKWebView"; +// [tabBarController addChildViewController:WKWebViewExampleController]; +// [self presentViewController:WKWebViewExampleController animated:YES completion:nil]; + [self.navigationController pushViewController:WKWebViewExampleController animated:YES]; +} +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Example Apps/ExampleApp.html b/Example Apps/ExampleApp.html index 06e7dc8a..e685c89c 100644 --- a/Example Apps/ExampleApp.html +++ b/Example Apps/ExampleApp.html @@ -9,24 +9,28 @@

WebViewJavascriptBridge Demo

+ -
+
diff --git a/Example Apps/TestConsole.html b/Example Apps/TestConsole.html new file mode 100644 index 00000000..cb4555ac --- /dev/null +++ b/Example Apps/TestConsole.html @@ -0,0 +1,16 @@ + + + + + +

WebViewJavascriptBridge Demo Test console.log

+ + + diff --git a/README.md b/README.md index fb14d2de..673bcf5e 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,70 @@ WebViewJavascriptBridge ======================= -[![Circle CI](https://img.shields.io/circleci/project/github/marcuswestin/WebViewJavascriptBridge.svg)](https://circleci.com/gh/marcuswestin/WebViewJavascriptBridge) +An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews. Also easy to get js console.log. -An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews, UIWebViews & WebViews. +More simple more light. Refactor WebViewJavascriptBridge with AOP +========================== -Migration Guide ---------------- - -When upgrading from v5.0.x to 6.0.x you will have to update the `setupWebViewJavascriptBridge` javascript snippet. See https://github.com/marcuswestin/WebViewJavascriptBridge#usage part 4). - -Who uses WebViewJavascriptBridge? ---------------------------------- -WebViewJavascriptBridge is used by a range of companies and projects. This is a small and incomplete sample list: - -- [Facebook Messenger](https://www.facebook.com/mobile/messenger) -- [Facebook Paper](https://facebook.com/paper) -- [Yardsale](http://www.getyardsale.com/) -- [EverTrue](http://www.evertrue.com/) -- [Game Insight](http://www.game-insight.com/) -- [Sush.io](http://www.sush.io) -- [Imbed](http://imbed.github.io/) -- [CareZone](https://carezone.com) -- [Hemlig](http://www.hemlig.co) -- [Altralogica](http://www.altralogica.it) -- [鼎盛中华](https://itunes.apple.com/us/app/ding-sheng-zhong-hua/id537273940?mt=8) -- [FRIL](https://fril.jp) -- [留白·WHITE](http://liubaiapp.com) -- [BrowZine](http://thirdiron.com/browzine/) -- ... & many more! - -Installation (iOS & OSX) ------------------------- +How to use ? +========================== ### Installation with CocoaPods Add this to your [podfile](https://guides.cocoapods.org/using/getting-started.html) and run `pod install` to install: ```ruby -pod 'WebViewJavascriptBridge', '~> 6.0' +pod 'SKJavaScriptBridge', '~> 1.0.3' +``` +If you can't find the last version, maybe you need to update local pod repo. +```ruby +pod repo update ``` ### Manual installation - 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". -Examples --------- - -See 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: - Usage ----- - 1) Import the header file and declare an ivar property: ```objc #import "WebViewJavascriptBridge.h" ``` - -... - ```objc -@property WebViewJavascriptBridge* bridge; +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, strong) WebViewJavascriptBridge* bridge; ``` -2) Instantiate WebViewJavascriptBridge with a WKWebView, UIWebView (iOS) or WebView (OSX): - ```objc -self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView]; + self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; + [self.view addSubview:self.webView]; + if(!_bridge){ + _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView + showJSconsole:YES + enableLogging:YES]; + } ``` -3) Register a handler in ObjC, and call a JS handler: +2) Register a handler in ObjC, and call a JS handler: ```objc -[self.bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) { +[_bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) { NSLog(@"ObjC Echo called with: %@", data); responseCallback(data); }]; -[self.bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) { +[_bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) { NSLog(@"ObjC received response: %@", responseData); }]; ``` - -4) Copy and paste `setupWebViewJavascriptBridge` into your JS: +3) Copy and paste `setupWebViewJavascriptBridge` into your JS: ```javascript function setupWebViewJavascriptBridge(callback) { - if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } - if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } - window.WVJBCallbacks = [callback]; - var WVJBIframe = document.createElement('iframe'); - WVJBIframe.style.display = 'none'; - WVJBIframe.src = 'https://__bridge_loaded__'; - document.documentElement.appendChild(WVJBIframe); - setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) + return callback(WebViewJavascriptBridge); } ``` - 5) Finally, call `setupWebViewJavascriptBridge` and then use the bridge to register handlers and call ObjC handlers: ```javascript @@ -118,121 +82,3 @@ setupWebViewJavascriptBridge(function(bridge) { }) ``` -Automatic reference counting (ARC) ----------------------------------- -This library relies on ARC, so if you use ARC in you project, all works fine. -But if your project have no ARC support, be sure to do next steps: - -1) In your Xcode project open project settings -> 'Build Phases' - -2) Expand 'Compile Sources' header and find all *.m files which are belongs to this library. Make attention on the 'Compiler Flags' in front of each source file in this list - -3) For each file add '-fobjc-arc' flag - -Now all WVJB files will be compiled with ARC support. - -Contributors & Forks --------------------- -Contributors: https://github.com/marcuswestin/WebViewJavascriptBridge/graphs/contributors - -Forks: https://github.com/marcuswestin/WebViewJavascriptBridge/network/members - -API Reference -------------- - -### ObjC API - -##### `[WebViewJavascriptBridge bridgeForWebView:(WKWebVIew/UIWebView/WebView*)webview` - -Create a javascript bridge for the given web view. - -Example: - -```objc -[WebViewJavascriptBridge bridgeForWebView:webView]; -``` - -##### `[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]` - -Register a handler called `handlerName`. The javascript can then call this handler with `WebViewJavascriptBridge.callHandler("handlerName")`. - -Example: - -```objc -[self.bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) { - responseCallback([NSNumber numberWithInt:[UIScreen mainScreen].bounds.size.height]); -}]; -[self.bridge registerHandler:@"log" handler:^(id data, WVJBResponseCallback responseCallback) { - NSLog(@"Log: %@", data); -}]; - -``` - -##### `[bridge callHandler:(NSString*)handlerName data:(id)data]` -##### `[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)callback]` - -Call the javascript handler called `handlerName`. If a `responseCallback` block is given the javascript handler can respond. - -Example: - -```objc -[self.bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"]; -[self.bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) { - NSLog(@"Current UIWebView page URL is: %@", responseData); -}]; -``` - -#### `[bridge setWebViewDelegate:(id)webViewDelegate]` - -Optionally, set a `WKNavigationDelegate/UIWebViewDelegate` if you need to respond to the [web view's lifecycle events](https://developer.apple.com/reference/uikit/uiwebviewdelegate). - -##### `[bridge disableJavscriptAlertBoxSafetyTimeout]` - -UNSAFE. Speed up bridge message passing by disabling the setTimeout safety check. It is only safe to disable this safety check if you do not call any of the javascript popup box functions (alert, confirm, and prompt). If you call any of these functions from the bridged javascript code, the app will hang. - -Example: - - [self.bridge disableJavscriptAlertBoxSafetyTimeout]; - - - -### Javascript API - -##### `bridge.registerHandler("handlerName", function(responseData) { ... })` - -Register a handler called `handlerName`. The ObjC can then call this handler with `[bridge callHandler:"handlerName" data:@"Foo"]` and `[bridge callHandler:"handlerName" data:@"Foo" responseCallback:^(id responseData) { ... }]` - -Example: - -```javascript -bridge.registerHandler("showAlert", function(data) { alert(data) }) -bridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) { - responseCallback(document.location.toString()) -}) -``` - - -##### `bridge.callHandler("handlerName", data)` -##### `bridge.callHandler("handlerName", data, function responseCallback(responseData) { ... })` - -Call an ObjC handler called `handlerName`. If a `responseCallback` function is given the ObjC handler can respond. - -Example: - -```javascript -bridge.callHandler("Log", "Foo") -bridge.callHandler("getScreenHeight", null, function(response) { - alert('Screen height:' + response) -}) -``` - - -##### `bridge.disableJavscriptAlertBoxSafetyTimeout()` - -Calling `bridge.disableJavscriptAlertBoxSafetyTimeout()` has the same effect as calling `[bridge disableJavscriptAlertBoxSafetyTimeout];` in ObjC. - -Example: - -```javascript -bridge.disableJavscriptAlertBoxSafetyTimeout() -``` diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h deleted file mode 100644 index 4e3404fc..00000000 --- a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// WKWebViewJavascriptBridge.h -// -// Created by @LokiMeyburg on 10/15/14. -// Copyright (c) 2014 @LokiMeyburg. All rights reserved. -// - -#if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1) -#define supportsWKWebView -#endif - -#if defined supportsWKWebView - -#import -#import "WebViewJavascriptBridgeBase.h" -#import - -@interface WKWebViewJavascriptBridge : NSObject - -+ (instancetype)bridgeForWebView:(WKWebView*)webView; -+ (void)enableLogging; - -- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; -- (void)removeHandler:(NSString*)handlerName; -- (void)callHandler:(NSString*)handlerName; -- (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 - -#endif diff --git a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m b/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m deleted file mode 100644 index 73c923db..00000000 --- a/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m +++ /dev/null @@ -1,198 +0,0 @@ -// -// WKWebViewJavascriptBridge.m -// -// Created by @LokiMeyburg on 10/15/14. -// Copyright (c) 2014 @LokiMeyburg. All rights reserved. -// - - -#import "WKWebViewJavascriptBridge.h" - -#if defined supportsWKWebView - -@implementation WKWebViewJavascriptBridge { - __weak WKWebView* _webView; - __weak id _webViewDelegate; - long _uniqueId; - WebViewJavascriptBridgeBase *_base; -} - -/* API - *****/ - -+ (void)enableLogging { [WebViewJavascriptBridgeBase enableLogging]; } - -+ (instancetype)bridgeForWebView:(WKWebView*)webView { - WKWebViewJavascriptBridge* bridge = [[self alloc] init]; - [bridge _setupInstance:webView]; - [bridge reset]; - return bridge; -} - -- (void)send:(id)data { - [self send:data responseCallback:nil]; -} - -- (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { - [_base 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 { - [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; -} - -- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { - _base.messageHandlers[handlerName] = [handler copy]; -} - -- (void)removeHandler:(NSString *)handlerName { - [_base.messageHandlers removeObjectForKey:handlerName]; -} - -- (void)reset { - [_base reset]; -} - -- (void)setWebViewDelegate:(id)webViewDelegate { - _webViewDelegate = webViewDelegate; -} - -- (void)disableJavscriptAlertBoxSafetyTimeout { - [_base disableJavscriptAlertBoxSafetyTimeout]; -} - -/* Internals - ***********/ - -- (void)dealloc { - _base = nil; - _webView = nil; - _webViewDelegate = nil; - _webView.navigationDelegate = nil; -} - - -/* WKWebView Specific Internals - ******************************/ - -- (void) _setupInstance:(WKWebView*)webView { - _webView = webView; - _webView.navigationDelegate = self; - _base = [[WebViewJavascriptBridgeBase alloc] init]; - _base.delegate = self; -} - - -- (void)WKFlushMessageQueue { - [_webView evaluateJavaScript:[_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]; - }]; -} - -- (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 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]; - } - else { - 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 { - 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]) { - [self WKFlushMessageQueue]; - } else { - [_base logUnkownMessage:url]; - } - decisionHandler(WKNavigationActionPolicyCancel); - return; - } - - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { - [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; - } else { - 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]; - } -} - - -- (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]; - } -} - -- (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]; - } -} - -- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { - [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; - return NULL; -} - - - -@end - - -#endif diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.h b/WebViewJavascriptBridge/WebViewJavascriptBridge.h old mode 100755 new mode 100644 index 1b64bb4e..002e64b3 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.h @@ -1,50 +1,26 @@ // // WebViewJavascriptBridge.h -// ExampleApp-iOS +// TestPod // -// Created by Marcus Westin on 6/14/13. -// Copyright (c) 2013 Marcus Westin. All rights reserved. +// Created by 侯森魁 on 2020/4/29. +// Copyright © 2020 侯森魁. All rights reserved. // #import #import "WebViewJavascriptBridgeBase.h" - -#if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1) -#define supportsWKWebView -#endif - -#if defined supportsWKWebView #import -#endif - -#if defined __MAC_OS_X_VERSION_MAX_ALLOWED - #define WVJB_PLATFORM_OSX - #define WVJB_WEBVIEW_TYPE WebView - #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject - #define WVJB_WEBVIEW_DELEGATE_INTERFACE NSObject -#elif defined __IPHONE_OS_VERSION_MAX_ALLOWED - #import - #define WVJB_PLATFORM_IOS - #define WVJB_WEBVIEW_TYPE UIWebView - #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject - #define WVJB_WEBVIEW_DELEGATE_INTERFACE NSObject -#endif - -@interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_INTERFACE +NS_ASSUME_NONNULL_BEGIN +@interface WebViewJavascriptBridge : NSObject -+ (instancetype)bridgeForWebView:(id)webView; -+ (instancetype)bridge:(id)webView; - -+ (void)enableLogging; -+ (void)setLogMaxLength:(int)length; - -- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; -- (void)removeHandler:(NSString*)handlerName; ++ (instancetype)bridgeForWebView:(WKWebView*)webView + showJSconsole:(BOOL)show + enableLogging:(BOOL)enable; +- (void)registerHandler:(NSString*)handlerName handler:(nullable WVJBHandler)handler; +- (void)removeHandler:( NSString* )handlerName; - (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; - +- (void)callHandler:(NSString*)handlerName data:(nullable id)data; +- (void)callHandler:(NSString*)handlerName data:(nullable id)data responseCallback:(nullable WVJBResponseCallback)responseCallback; @end + +NS_ASSUME_NONNULL_END diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge.m b/WebViewJavascriptBridge/WebViewJavascriptBridge.m old mode 100755 new mode 100644 index e74a6e24..79f48f12 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridge.m @@ -1,68 +1,29 @@ // // WebViewJavascriptBridge.m -// ExampleApp-iOS +// TestPod // -// Created by Marcus Westin on 6/14/13. -// Copyright (c) 2013 Marcus Westin. All rights reserved. +// Created by 侯森魁 on 2020/4/29. +// Copyright © 2020 侯森魁. All rights reserved. // #import "WebViewJavascriptBridge.h" +#import "WebViewJavascriptLeakAvoider.h" +#define kBridgePrefix @"__bridge__" -#if defined(supportsWKWebView) -#import "WKWebViewJavascriptBridge.h" -#endif - -#if __has_feature(objc_arc_weak) - #define WVJB_WEAK __weak -#else - #define WVJB_WEAK __unsafe_unretained -#endif - -@implementation WebViewJavascriptBridge { - WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView; - WVJB_WEAK id _webViewDelegate; - long _uniqueId; - WebViewJavascriptBridgeBase *_base; +@implementation WebViewJavascriptBridge { + WKWebView* _webView; + long _uniqueId; + WebViewJavascriptBridgeBase *_base; + BOOL _showJSconsole; + BOOL _enableLogging; } -/* API - *****/ - -+ (void)enableLogging { - [WebViewJavascriptBridgeBase enableLogging]; -} -+ (void)setLogMaxLength:(int)length { - [WebViewJavascriptBridgeBase setLogMaxLength:length]; -} - -+ (instancetype)bridgeForWebView:(id)webView { - return [self bridge:webView]; -} -+ (instancetype)bridge:(id)webView { -#if defined supportsWKWebView - if ([webView isKindOfClass:[WKWebView class]]) { - return (WebViewJavascriptBridge*) [WKWebViewJavascriptBridge bridgeForWebView:webView]; - } -#endif - if ([webView isKindOfClass:[WVJB_WEBVIEW_TYPE class]]) { - WebViewJavascriptBridge* bridge = [[self alloc] init]; - [bridge _platformSpecificSetup:webView]; - return bridge; - } - [NSException raise:@"BadWebViewType" format:@"Unknown web view type."]; - 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]; ++ (instancetype)bridgeForWebView:(WKWebView*)webView + showJSconsole:(BOOL)show + enableLogging:(BOOL)enable { + WebViewJavascriptBridge* bridge = [[self alloc] init]; + [bridge _setupInstance:webView showJSconsole:show enableLogging:enable]; + return bridge; } - (void)callHandler:(NSString *)handlerName { @@ -85,127 +46,188 @@ - (void)removeHandler:(NSString *)handlerName { [_base.messageHandlers removeObjectForKey:handlerName]; } -- (void)disableJavscriptAlertBoxSafetyTimeout { - [_base disableJavscriptAlertBoxSafetyTimeout]; -} - - -/* Platform agnostic internals - *****************************/ - -- (void)dealloc { - [self _platformSpecificDealloc]; - _base = nil; - _webView = nil; - _webViewDelegate = nil; -} - -- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { - return [_webView stringByEvaluatingJavaScriptFromString:javascriptCommand]; -} -#if defined WVJB_PLATFORM_OSX -/* Platform specific internals: OSX - **********************************/ - -- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { +- (void)_setupInstance:(WKWebView*)webView showJSconsole:(BOOL)show enableLogging:(BOOL)enable{ _webView = webView; - _webView.policyDelegate = self; _base = [[WebViewJavascriptBridgeBase alloc] init]; _base.delegate = self; + _showJSconsole = show; + _enableLogging = enable; + + [self addScriptMessageHandler]; + [self _injectJavascriptFile]; +} +- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { + NSString * body = (NSString * )message.body; + if ([self _filterMessage:body]) { + NSMutableString *mstr = [NSMutableString stringWithString:body]; + [mstr replaceOccurrencesOfString:kBridgePrefix withString:@"" options:0 range:NSMakeRange(0, 10)]; + [_base flushMessageQueue:mstr]; + } } - -- (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; } - - 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]; - } else { - [_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]; +- (void)_injectJavascriptFile { + NSString *bridge_js = WebViewJavascriptBridge_js(); + //injected the method when H5 starts to create the DOM tree + WKUserScript * bridge_userScript = [[WKUserScript alloc]initWithSource:bridge_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [_webView.configuration.userContentController addUserScript:bridge_userScript]; + if (_showJSconsole) { + NSString *console_log_js = WebViewJavascriptBridge_console_log_js(); + WKUserScript * console_log_userScript = [[WKUserScript alloc]initWithSource:console_log_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [_webView.configuration.userContentController addUserScript:console_log_userScript]; } } +- (void) addScriptMessageHandler { + [_webView.configuration.userContentController addScriptMessageHandler:[[WebViewJavascriptLeakAvoider alloc]initWithDelegate:self] name:@"pipe"]; +} - - -#elif defined WVJB_PLATFORM_IOS -/* Platform specific internals: iOS - **********************************/ - -- (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { - _webView = webView; - _webView.delegate = self; - _base = [[WebViewJavascriptBridgeBase alloc] init]; - _base.delegate = self; +- (void)removeScriptMessageHandler { + [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"pipe"]; } -- (void) _platformSpecificDealloc { - _webView.delegate = nil; +- (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { + [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; + return NULL; } -- (void)webViewDidFinishLoad:(UIWebView *)webView { - if (webView != _webView) { return; } - - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { - [strongDelegate webViewDidFinishLoad:webView]; +- (NSString *)_filterMessage:(NSString *) message { + if (_enableLogging) { + NSLog(@"All WVJB RCVD:%@",message); } + if (message&& [message isKindOfClass:[NSString class]] && [message containsString:kBridgePrefix]) + { + return message; + } + return nil; } -- (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]; - } +- (void)dealloc { + [self removeScriptMessageHandler]; } -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { - if (webView != _webView) { return YES; } +NSString * WebViewJavascriptBridge_js() { +#define __WVJB_js_func__(x) #x - 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]; - } else { - [_base logUnkownMessage:url]; + // BEGIN preprocessorJSCode + static NSString * preprocessorJSCode = @__WVJB_js_func__( + ;(function(window) { + + window.WebViewJavascriptBridge = { + registerHandler: registerHandler, + callHandler: callHandler, + _handleMessageFromObjC: _handleMessageFromObjC + }; + + var sendMessageQueue = []; + var messageHandlers = {}; + var responseCallbacks = {}; + var uniqueId = 1; + + function registerHandler(handlerName, handler) { + messageHandlers[handlerName] = handler; } - 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; } + + function callHandler(handlerName, data, responseCallback) { + if (arguments.length === 2 && typeof data == 'function') { + responseCallback = data; + data = null; + } + _doSend({ handlerName:handlerName, data:data }, responseCallback); + } + function _doSend(message, responseCallback) { + if (responseCallback) { + var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); + responseCallbacks[callbackId] = responseCallback; + message['callbackId'] = callbackId; + } + sendMessageQueue.push(message); + window.webkit.messageHandlers.pipe.postMessage('__bridge__'+ JSON.stringify(sendMessageQueue)); + sendMessageQueue = []; + } + + function _dispatchMessageFromObjC(messageJSON) { + _doDispatchMessageFromObjC(); + + function _doDispatchMessageFromObjC() { + var message = JSON.parse(messageJSON); + var messageHandler; + var responseCallback; + + if (message.responseId) { + responseCallback = responseCallbacks[message.responseId]; + if (!responseCallback) { + + return; + } + + responseCallback(message.responseData); + delete responseCallbacks[message.responseId]; + } else { + if (message.callbackId) { + var callbackResponseId = message.callbackId; + responseCallback = function(responseData) { + _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); + }; + } + var handler = messageHandlers[message.handlerName]; + if (!handler) { + console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); + } else { + handler(message.data, responseCallback); + } + } + } + } + function _handleMessageFromObjC(messageJSON) { + _dispatchMessageFromObjC(messageJSON); + } + })(window); + ); // END preprocessorJSCode - __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; - if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { - [strongDelegate webViewDidStartLoad:webView]; - } -} +#undef __WVJB_js_func__ + return preprocessorJSCode; +}; -#endif +NSString * WebViewJavascriptBridge_console_log_js() { +#define __WVJB_js_func__(x) #x + + // BEGIN preprocessorJSCode + static NSString * preprocessorJSCode = @__WVJB_js_func__( + ;(function(window) { + let printObject = function (obj) { + let output = ""; + if (obj === null) { + output += "null"; + } + else if (typeof(obj) == "undefined") { + output += "undefined"; + } + else if (typeof obj ==='object'){ + output+="{"; + for(let key in obj){ + let value = obj[key]; + output+= "\""+key+"\""+":"+"\""+value+"\""+","; + } + output = output.substr(0, output.length - 1); + output+="}"; + } + else { + output = "" + obj; + } + return output; + }; + window.console.log = (function (oriLogFunc,printObject) { + return function (str) { + str = printObject(str); + window.webkit.messageHandlers.pipe.postMessage(str); + oriLogFunc.call(window.console, str); + } + })(window.console.log,printObject); + + })(window); + ); // END preprocessorJSCode + +#undef __WVJB_js_func__ + return preprocessorJSCode; +}; @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h old mode 100755 new mode 100644 index 54d80acc..6b723cde --- a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h +++ b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h @@ -1,46 +1,29 @@ // // WebViewJavascriptBridgeBase.h +// TestPod // -// Created by @LokiMeyburg on 10/15/14. -// Copyright (c) 2014 @LokiMeyburg. All rights reserved. +// Created by 侯森魁 on 2020/4/29. +// Copyright © 2020 侯森魁. All rights reserved. // #import -#define kOldProtocolScheme @"wvjbscheme" -#define kNewProtocolScheme @"https" -#define kQueueHasMessage @"__wvjb_queue_message__" -#define kBridgeLoaded @"__bridge_loaded__" - -typedef void (^WVJBResponseCallback)(id responseData); -typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); -typedef NSDictionary WVJBMessage; - +NS_ASSUME_NONNULL_BEGIN @protocol WebViewJavascriptBridgeBaseDelegate - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand; @end +typedef NSDictionary WVJBMessage; +typedef void (^WVJBResponseCallback)(id responseData); +typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); @interface WebViewJavascriptBridgeBase : NSObject - - @property (weak, nonatomic) id delegate; -@property (strong, nonatomic) NSMutableArray* startupMessageQueue; @property (strong, nonatomic) NSMutableDictionary* responseCallbacks; @property (strong, nonatomic) NSMutableDictionary* messageHandlers; @property (strong, nonatomic) WVJBHandler messageHandler; -+ (void)enableLogging; -+ (void)setLogMaxLength:(int)length; -- (void)reset; - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; - (void)flushMessageQueue:(NSString *)messageQueueString; -- (void)injectJavascriptFile; -- (BOOL)isWebViewJavascriptBridgeURL:(NSURL*)url; -- (BOOL)isQueueMessageURL:(NSURL*)urll; -- (BOOL)isBridgeLoadedURL:(NSURL*)urll; -- (void)logUnkownMessage:(NSURL*)url; -- (NSString *)webViewJavascriptCheckCommand; -- (NSString *)webViewJavascriptFetchQueyCommand; -- (void)disableJavscriptAlertBoxSafetyTimeout; - @end + +NS_ASSUME_NONNULL_END diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m old mode 100755 new mode 100644 index 3ec26ed4..a519cb68 --- a/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m +++ b/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m @@ -1,47 +1,24 @@ // // WebViewJavascriptBridgeBase.m +// TestPod // -// Created by @LokiMeyburg on 10/15/14. -// Copyright (c) 2014 @LokiMeyburg. All rights reserved. +// Created by 侯森魁 on 2020/4/29. +// Copyright © 2020 侯森魁. All rights reserved. // -#import #import "WebViewJavascriptBridgeBase.h" -#import "WebViewJavascriptBridge_JS.h" - @implementation WebViewJavascriptBridgeBase { - __weak id _webViewDelegate; - long _uniqueId; + long _uniqueId; } - -static bool logging = false; -static int logMaxLength = 500; - -+ (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]; _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]; - _uniqueId = 0; -} - - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { NSMutableDictionary* message = [NSMutableDictionary dictionary]; @@ -58,7 +35,7 @@ - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallbac if (handlerName) { message[@"handlerName"] = handlerName; } - [self _queueMessage:message]; + [self _dispatchMessage:message]; } - (void)flushMessageQueue:(NSString *)messageQueueString{ @@ -73,8 +50,6 @@ - (void)flushMessageQueue:(NSString *)messageQueueString{ NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); continue; } - [self _log:@"RCVD" json:message]; - NSString* responseId = message[@"responseId"]; if (responseId) { WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; @@ -90,7 +65,7 @@ - (void)flushMessageQueue:(NSString *)messageQueueString{ } WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; - [self _queueMessage:msg]; + [self _dispatchMessage:msg]; }; } else { responseCallback = ^(id ignoreResponseData) { @@ -110,74 +85,20 @@ - (void)flushMessageQueue:(NSString *)messageQueueString{ } } -- (void)injectJavascriptFile { - NSString *js = WebViewJavascriptBridge_js(); - [self _evaluateJavascript:js]; - if (self.startupMessageQueue) { - NSArray* queue = self.startupMessageQueue; - self.startupMessageQueue = nil; - for (id queuedMessage in queue) { - [self _dispatchMessage:queuedMessage]; - } - } -} - -- (BOOL)isWebViewJavascriptBridgeURL:(NSURL*)url { - if (![self isSchemeMatch:url]) { - return NO; - } - return [self isBridgeLoadedURL:url] || [self isQueueMessageURL:url]; -} - -- (BOOL)isSchemeMatch:(NSURL*)url { - NSString* scheme = url.scheme.lowercaseString; - return [scheme isEqualToString:kNewProtocolScheme] || [scheme isEqualToString:kOldProtocolScheme]; -} - -- (BOOL)isQueueMessageURL:(NSURL*)url { - NSString* host = url.host.lowercaseString; - return [self isSchemeMatch:url] && [host isEqualToString:kQueueHasMessage]; -} - -- (BOOL)isBridgeLoadedURL:(NSURL*)url { - NSString* host = url.host.lowercaseString; - return [self isSchemeMatch:url] && [host isEqualToString:kBridgeLoaded]; -} - -- (void)logUnkownMessage:(NSURL*)url { - NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@", [url absoluteString]); -} - -- (NSString *)webViewJavascriptCheckCommand { - return @"typeof WebViewJavascriptBridge == \'object\';"; -} - -- (NSString *)webViewJavascriptFetchQueyCommand { - return @"WebViewJavascriptBridge._fetchQueue();"; +- (NSString *)_serializeMessage:(id)message pretty:(BOOL)pretty{ + return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:(NSJSONWritingOptions)(pretty ? NSJSONWritingPrettyPrinted : 0) error:nil] encoding:NSUTF8StringEncoding]; } -- (void)disableJavscriptAlertBoxSafetyTimeout { - [self sendData:nil responseCallback:nil handlerName:@"_disableJavascriptAlertBoxSafetyTimeout"]; +- (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { + return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; } -// Private -// ------------------------------------------- - - (void) _evaluateJavascript:(NSString *)javascriptCommand { [self.delegate _evaluateJavascript:javascriptCommand]; } -- (void)_queueMessage:(WVJBMessage*)message { - if (self.startupMessageQueue) { - [self.startupMessageQueue addObject:message]; - } else { - [self _dispatchMessage:message]; - } -} - - (void)_dispatchMessage:(WVJBMessage*)message { NSString *messageJSON = [self _serializeMessage:message pretty:NO]; - [self _log:@"SEND" json:messageJSON]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; @@ -198,24 +119,4 @@ - (void)_dispatchMessage:(WVJBMessage*)message { } } -- (NSString *)_serializeMessage:(id)message pretty:(BOOL)pretty{ - return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:(NSJSONWritingOptions)(pretty ? NSJSONWritingPrettyPrinted : 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 pretty:YES]; - } - if ([json length] > logMaxLength) { - NSLog(@"WVJB %@: %@ [...]", action, [json substringToIndex:logMaxLength]); - } else { - NSLog(@"WVJB %@: %@", action, json); - } -} - @end diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h b/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h deleted file mode 100644 index 9c857f16..00000000 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h +++ /dev/null @@ -1,3 +0,0 @@ -#import - -NSString * WebViewJavascriptBridge_js(void); diff --git a/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.m b/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.m deleted file mode 100644 index 670a552f..00000000 --- a/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.m +++ /dev/null @@ -1,139 +0,0 @@ -// This file contains the source for the Javascript side of the -// WebViewJavascriptBridge. It is plaintext, but converted to an NSString -// via some preprocessor tricks. -// -// Previous implementations of WebViewJavascriptBridge loaded the javascript source -// from a resource. This worked fine for app developers, but library developers who -// included the bridge into their library, awkwardly had to ask consumers of their -// library to include the resource, violating their encapsulation. By including the -// Javascript as a string resource, the encapsulation of the library is maintained. - -#import "WebViewJavascriptBridge_JS.h" - -NSString * WebViewJavascriptBridge_js() { - #define __wvjb_js_func__(x) #x - - // BEGIN preprocessorJSCode - static NSString * preprocessorJSCode = @__wvjb_js_func__( -;(function() { - if (window.WebViewJavascriptBridge) { - return; - } - - if (!window.onerror) { - window.onerror = function(msg, url, line) { - console.log("WebViewJavascriptBridge: ERROR:" + msg + "@" + url + ":" + line); - } - } - window.WebViewJavascriptBridge = { - registerHandler: registerHandler, - callHandler: callHandler, - disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout, - _fetchQueue: _fetchQueue, - _handleMessageFromObjC: _handleMessageFromObjC - }; - - var messagingIframe; - var sendMessageQueue = []; - var messageHandlers = {}; - - var CUSTOM_PROTOCOL_SCHEME = 'https'; - var QUEUE_HAS_MESSAGE = '__wvjb_queue_message__'; - - var responseCallbacks = {}; - var uniqueId = 1; - var dispatchMessagesWithTimeoutSafety = true; - - function registerHandler(handlerName, handler) { - messageHandlers[handlerName] = handler; - } - - function callHandler(handlerName, data, responseCallback) { - if (arguments.length == 2 && typeof data == 'function') { - responseCallback = data; - data = null; - } - _doSend({ handlerName:handlerName, data:data }, responseCallback); - } - function disableJavscriptAlertBoxSafetyTimeout() { - dispatchMessagesWithTimeoutSafety = false; - } - - function _doSend(message, responseCallback) { - if (responseCallback) { - var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); - responseCallbacks[callbackId] = responseCallback; - message['callbackId'] = callbackId; - } - sendMessageQueue.push(message); - messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; - } - - function _fetchQueue() { - var messageQueueString = JSON.stringify(sendMessageQueue); - sendMessageQueue = []; - return messageQueueString; - } - - function _dispatchMessageFromObjC(messageJSON) { - if (dispatchMessagesWithTimeoutSafety) { - setTimeout(_doDispatchMessageFromObjC); - } else { - _doDispatchMessageFromObjC(); - } - - function _doDispatchMessageFromObjC() { - var message = JSON.parse(messageJSON); - var messageHandler; - var responseCallback; - - if (message.responseId) { - responseCallback = responseCallbacks[message.responseId]; - if (!responseCallback) { - return; - } - responseCallback(message.responseData); - delete responseCallbacks[message.responseId]; - } else { - if (message.callbackId) { - var callbackResponseId = message.callbackId; - responseCallback = function(responseData) { - _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); - }; - } - - var handler = messageHandlers[message.handlerName]; - if (!handler) { - console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); - } else { - handler(message.data, responseCallback); - } - } - } - } - - function _handleMessageFromObjC(messageJSON) { - _dispatchMessageFromObjC(messageJSON); - } - - messagingIframe = document.createElement('iframe'); - messagingIframe.style.display = 'none'; - messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; - document.documentElement.appendChild(messagingIframe); - - registerHandler("_disableJavascriptAlertBoxSafetyTimeout", disableJavscriptAlertBoxSafetyTimeout); - - setTimeout(_callWVJBCallbacks, 0); - function _callWVJBCallbacks() { - var callbacks = window.WVJBCallbacks; - delete window.WVJBCallbacks; - for (var i=0; i +#import +NS_ASSUME_NONNULL_BEGIN + +@interface WebViewJavascriptLeakAvoider : NSObject +@property(nonatomic,weak)id delegate; +- (instancetype)initWithDelegate:(id )delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/WebViewJavascriptBridge/WebViewJavascriptLeakAvoider.m b/WebViewJavascriptBridge/WebViewJavascriptLeakAvoider.m new file mode 100644 index 00000000..6cbcb906 --- /dev/null +++ b/WebViewJavascriptBridge/WebViewJavascriptLeakAvoider.m @@ -0,0 +1,21 @@ +// +// LeakAvoider.m +// ExampleApp-iOS +// +// Created by 侯森魁 on 2020/4/20. +// Copyright © 2020 Marcus Westin. All rights reserved. +// + +#import "WebViewJavascriptLeakAvoider.h" + +@implementation WebViewJavascriptLeakAvoider +- (instancetype)initWithDelegate:(id )delegate { + if (self = [super init]) { + self.delegate = delegate; + } + return self; +} +- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { + [self.delegate userContentController:userContentController didReceiveScriptMessage:message]; +} +@end