├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Changelog ├── Example Apps ├── ExampleApp-OSX.xcodeproj │ └── project.pbxproj ├── ExampleApp-OSX │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── ExampleApp-OSX-Info.plist │ ├── ExampleApp-OSX-Prefix.pch │ ├── MainMenu.xib │ ├── en.lproj │ │ ├── Credits.rtf │ │ └── InfoPlist.strings │ └── main.m ├── ExampleApp-iOS.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── ExampleApp-iOS.xcscheme ├── ExampleApp-iOS │ ├── Default-568h@2x.png │ ├── ExampleApp-iOS-Info.plist │ ├── ExampleApp-iOS-Prefix.pch │ ├── ExampleAppDelegate.h │ ├── ExampleAppDelegate.m │ ├── ExampleWKWebViewController.h │ ├── ExampleWKWebViewController.m │ ├── FirstViewController.h │ ├── FirstViewController.m │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m ├── ExampleApp.html ├── ExampleSwiftApp-iOS │ ├── ExampleSwiftApp-iOS.xcodeproj │ │ └── project.pbxproj │ ├── ExampleSwiftApp-iOS.xcworkspace │ │ └── contents.xcworkspacedata │ ├── ExampleSwiftApp-iOS │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── ExampleSwiftApp-iOSTests │ │ ├── ExampleSwiftApp_iOSTests.swift │ │ └── Info.plist │ ├── Podfile │ ├── Podfile.lock │ ├── Pods │ │ ├── Local Podspecs │ │ │ └── WebViewJavascriptBridge.podspec.json │ │ ├── Manifest.lock │ │ ├── Pods.xcodeproj │ │ │ └── project.pbxproj │ │ └── Target Support Files │ │ │ ├── Pods-ExampleSwiftApp-iOS │ │ │ ├── Info.plist │ │ │ ├── Pods-ExampleSwiftApp-iOS-acknowledgements.markdown │ │ │ ├── Pods-ExampleSwiftApp-iOS-acknowledgements.plist │ │ │ ├── Pods-ExampleSwiftApp-iOS-dummy.m │ │ │ ├── Pods-ExampleSwiftApp-iOS-frameworks.sh │ │ │ ├── Pods-ExampleSwiftApp-iOS-resources.sh │ │ │ ├── Pods-ExampleSwiftApp-iOS-umbrella.h │ │ │ ├── Pods-ExampleSwiftApp-iOS.debug.xcconfig │ │ │ ├── Pods-ExampleSwiftApp-iOS.modulemap │ │ │ └── Pods-ExampleSwiftApp-iOS.release.xcconfig │ │ │ ├── Pods-ExampleSwiftApp-iOSTests │ │ │ ├── Info.plist │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-acknowledgements.markdown │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-acknowledgements.plist │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-dummy.m │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-frameworks.sh │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-resources.sh │ │ │ ├── Pods-ExampleSwiftApp-iOSTests-umbrella.h │ │ │ ├── Pods-ExampleSwiftApp-iOSTests.debug.xcconfig │ │ │ ├── Pods-ExampleSwiftApp-iOSTests.modulemap │ │ │ └── Pods-ExampleSwiftApp-iOSTests.release.xcconfig │ │ │ └── WebViewJavascriptBridge │ │ │ ├── Info.plist │ │ │ ├── WebViewJavascriptBridge-dummy.m │ │ │ ├── WebViewJavascriptBridge-prefix.pch │ │ │ ├── WebViewJavascriptBridge-umbrella.h │ │ │ ├── WebViewJavascriptBridge.modulemap │ │ │ └── WebViewJavascriptBridge.xcconfig │ └── echo.html └── TestConsole.html ├── LICENSE ├── Makefile ├── README.md ├── Roadmap.md ├── Tests ├── Default-568h@2x.png ├── WebViewJavascriptBridge.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── WebViewJavascriptBridge.xcscheme ├── WebViewJavascriptBridgeTestHost │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Info.plist │ ├── WebViewJavascriptBridgeTestHost-Bridging-Header.h │ └── main.m └── WebViewJavascriptBridgeTests │ ├── BridgeTests.m │ ├── BridgeTests.swift │ ├── Info.plist │ ├── WebViewJavascriptBridgeTests-Bridging-Header.h │ └── echo.html ├── WebViewJavascriptBridge.podspec ├── WebViewJavascriptBridge ├── WebViewJavascriptBridge.h ├── WebViewJavascriptBridge.m ├── WebViewJavascriptBridgeBase.h ├── WebViewJavascriptBridgeBase.m ├── WebViewJavascriptLeakAvoider.h └── WebViewJavascriptLeakAvoider.m └── circle.yml /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # WVJB Bug Report 2 | 3 | Thanks for reporting an issue with WebViewJavascriptBridge. 4 | 5 | ### Do these 4 things and I will fix your problem! 6 | 7 | 1. Go to https://github.com/marcuswestin/WebViewJavascriptBridge and click Fork. 8 | 2. Clone your fork, `cd` into it and run `make test`. All tests should pass! 9 | 3. Edit `Tests/WebViewJavascriptBridgeTests/BridgeTests.m` and create a new, failing test which demostrates your issue. 10 | 4. Create a pull request for https://github.com/marcuswestin/WebViewJavascriptBridge 11 | 12 | #### That's it! 13 | 14 | I will take it from there and promise that I'll fix your problem ASAP. 15 | 16 | #### If you don't do this then I can't help you! 17 | 18 | And I probably won't :) 19 | 20 | Cheers, 21 | @marcuswestin 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Before your create your PR: 2 | 3 | #### Please add tests for any new or changed functionality! 4 | 5 | 1. Edit `Tests/WebViewJavascriptBridgeTests/BridgeTests.m` 6 | 2. Create a new test which demostrates your changes. 7 | 3. Run `make test` and make sure your test is passing 8 | 4. That's it! 9 | 10 | #### Thanks for improving WebViewJavascriptBridge! 11 | 12 | Cheers, 13 | @marcuswestin 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | *.DS_Store 3 | 4 | # Xcode 5 | *.pbxuser 6 | *.mode1v3 7 | *.mode2v3 8 | *.perspectivev3 9 | *.xcuserstate 10 | *.xcworkspace/ 11 | xcuserdata/ 12 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | WebViewJavascriptBridge Changelog 2 | ================================= 3 | 4 | Release Checklist 5 | ----------------- 6 | - gitu-update 7 | - Note Changelog 8 | - Bump `WebViewJavascriptBridge.podspec` version "X.Y.Z" 9 | - gitm-commit "vX.Y.Z" 10 | - gitt-tag "vX.Y.Z" 11 | - pod trunk push 12 | 13 | Version History 14 | --------------- 15 | 16 | v5.1.1 17 | + Swift unit tests and examples 18 | + Implement removeHandler 19 | 20 | v5.1.0 21 | + A single instantiation function for all webview types. 22 | + Improved test runner. 23 | + New instructions & templates for github issues and pull requests. 24 | 25 | v5.0.5 26 | + Run all tests for both UIWebView and WKWebView webviews/bridges. 27 | + Allow for calling handlers from JS with just a handler name and responseCallback function (#184). 28 | 29 | v5.0.3 & v5.0.4 30 | + Recalled builds :) 31 | 32 | v5.0.2 33 | + Fix bug that could cause a crash if the webview loads a new page immediately after JS sends a message. 34 | 35 | v5.0.1 36 | + Removed `WebViewJavascriptBridge -reset`. It should never have been exposed as a public API. 37 | + Fixed compilation in C99 mode 38 | + Inline JS source code. WVJB no longer requires `WebViewJavascriptBridge.js.txt` to be included as a resource. 39 | + Automated testing: see `make test` 40 | + Added Makefile with common commands 41 | + Significantly simplified and improved wvjb load detection 42 | + Simplify API by focusing on explicitly named handlers instead of a default handler and plain `send`. 43 | 44 | v4.1.4 45 | + Improve how WVJB handles the case when there is no ObjC handler for a message received from js. 46 | + If an objc handler throws and exception, let it bubble up to the webkit engine instead of catching it in WVJB. 47 | 48 | v4.1.3 49 | + Update podspec file with tag 50 | 51 | v4.1.2 52 | + Fix bug: webViewDidStart/FinishLoad were called twice and isLoading was always true (#86) 53 | 54 | v4.1.1 55 | + Better JS initialization script (thank @refractalize!) 56 | + When passing nil to an objc response callback, replace it with [NSNull null] (becomes null in js) 57 | 58 | v4.1.0 59 | + Allow for sending null/nil data packets 60 | + Drop support for JSONKit 61 | + Clean up internal represenation of messages 62 | 63 | v4.0.2 64 | + Fix NSInvalidArgumentException: "attempt to insert nil object" when using shorthand -callHandler: 65 | + Fix sending messages including __WVJB_MESSAGE_SEPERATOR__ string 66 | 67 | v4.0.1 68 | + Fix detection of arc_weak support 69 | 70 | v4.0.0 71 | + Consolidate platform-specific code into a single WebViewJavascriptBridge.m/h using macros (57ee322a4c5310eadd28b28f4d8522cd54123301) 72 | + Bugfix: Don't make navigation decisions for webviews we don't control (254ea00267f8c1e03727885f4e1e0fd5f5c78be8) 73 | 74 | v3.1.0 75 | + Dont inject the WVJB bridge until all requests have finished loading (61b853) 76 | + Add podspec file (818d49cfc) 77 | + Memory leaks fixed (b06988f1, 20ce1b0b) 78 | + New major contributor @peyton! 79 | 80 | v3.0.0 81 | + OSX Support 82 | + New major contributor @oakho! 83 | 84 | v2.1.2 85 | + Copy handler and response blocks 86 | 87 | v2.1.1 88 | + Handle edge cases gracefully (e.g. don't crash on unknown command or unexpected response) 89 | 90 | v2.1.0 91 | + Remove WVJBResponse object and the notion of responding with an error. See 4ab41bb4d7. 92 | 93 | v2.0.0 94 | + Messages are objects instead of strings. Supports NSDictionary*/Objects, NSArray*/Arrays, NSNumber*/Number & NSString*/String. 95 | + Messages are encoded with NSJSONSerialization. Optional fallback to JSONKit for iOS 4 support. 96 | + Messages can expect responses. A message received with an expected response is accompanied by a WVJBResponse* object. 97 | + Handlers can be registered by name, and called with data and an optional expected response. 98 | + Responses expect either an error or data (`-(void)respond:(id)data`, -(void)respondWithError:(id)error) 99 | 100 | v0.0.1 101 | + ObjC: A WebViewJavascriptBridge class (a UIWebViewDelegate) that enables message passing to and from the JS 102 | + ObjC: A protocol called WebViewJavascriptBridgeDelegate that lets you handle messages received from the JS 103 | + JS: Event when the bridge is ready - document.addEventListener('WebViewJavascriptBridgeReady', function() {}, false) 104 | + JS: Ability to set your message handler - WebViewJavascriptBridge.setMessageHandler(function() {}) 105 | + JS: Function to send messages - WebViewJavascriptBridge.sendMessage('a message'); 106 | + All messages are strings. Use JSON in your js and e.g. JSONKit in iOS to send structured messages 107 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A2417641106004C7401 /* Cocoa.framework */; }; 11 | 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A2D17641106004C7401 /* InfoPlist.strings */; }; 12 | 2C136A3117641106004C7401 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3017641106004C7401 /* main.m */; }; 13 | 2C136A3517641106004C7401 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A3317641106004C7401 /* Credits.rtf */; }; 14 | 2C136A3817641106004C7401 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C136A3717641106004C7401 /* AppDelegate.m */; }; 15 | 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C136A4117641236004C7401 /* WebKit.framework */; }; 16 | 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2C136A5917642704004C7401 /* ExampleApp.html */; }; 17 | 2CF17F5317D8AACF006E828B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CF17F5217D8AACF006E828B /* MainMenu.xib */; }; 18 | EF5DC17623474A0A00F81F96 /* WKWebView+JavaScriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 2C136A2117641106004C7401 /* ExampleApp-OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 2C136A2417641106004C7401 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 24 | 2C136A2717641106004C7401 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 25 | 2C136A2817641106004C7401 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 26 | 2C136A2917641106004C7401 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 27 | 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ExampleApp-OSX-Info.plist"; sourceTree = ""; }; 28 | 2C136A2E17641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 29 | 2C136A3017641106004C7401 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-OSX-Prefix.pch"; sourceTree = ""; }; 31 | 2C136A3417641106004C7401 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 32 | 2C136A3617641106004C7401 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | 2C136A3717641106004C7401 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | 2C136A4117641236004C7401 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 35 | 2C136A5917642704004C7401 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; 36 | 2CF17F5217D8AACF006E828B /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; 37 | EF5DC17423474A0A00F81F96 /* WKWebView+JavaScriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WKWebView+JavaScriptBridge.h"; sourceTree = ""; }; 38 | EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WKWebView+JavaScriptBridge.m"; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 2C136A1E17641106004C7401 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | 2C136A4217641236004C7401 /* WebKit.framework in Frameworks */, 47 | 2C136A2517641106004C7401 /* Cocoa.framework in Frameworks */, 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | 2C136A1817641106004C7401 = { 55 | isa = PBXGroup; 56 | children = ( 57 | 2C136A4117641236004C7401 /* WebKit.framework */, 58 | 2C136A2A17641106004C7401 /* ExampleApp-OSX */, 59 | 2C136A2317641106004C7401 /* Frameworks */, 60 | 2C136A2217641106004C7401 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | 2C136A2217641106004C7401 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2C136A2117641106004C7401 /* ExampleApp-OSX.app */, 68 | ); 69 | name = Products; 70 | sourceTree = ""; 71 | }; 72 | 2C136A2317641106004C7401 /* Frameworks */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 2C136A2417641106004C7401 /* Cocoa.framework */, 76 | 2C136A2617641106004C7401 /* Other Frameworks */, 77 | ); 78 | name = Frameworks; 79 | sourceTree = ""; 80 | }; 81 | 2C136A2617641106004C7401 /* Other Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 2C136A2717641106004C7401 /* AppKit.framework */, 85 | 2C136A2817641106004C7401 /* CoreData.framework */, 86 | 2C136A2917641106004C7401 /* Foundation.framework */, 87 | ); 88 | name = "Other Frameworks"; 89 | sourceTree = ""; 90 | }; 91 | 2C136A2A17641106004C7401 /* ExampleApp-OSX */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 2C136A3617641106004C7401 /* AppDelegate.h */, 95 | 2C136A3717641106004C7401 /* AppDelegate.m */, 96 | 2C136A5917642704004C7401 /* ExampleApp.html */, 97 | 2CF17F5217D8AACF006E828B /* MainMenu.xib */, 98 | 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */, 99 | 2C136A2B17641106004C7401 /* Supporting Files */, 100 | ); 101 | path = "ExampleApp-OSX"; 102 | sourceTree = ""; 103 | }; 104 | 2C136A2B17641106004C7401 /* Supporting Files */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 2C136A2C17641106004C7401 /* ExampleApp-OSX-Info.plist */, 108 | 2C136A2D17641106004C7401 /* InfoPlist.strings */, 109 | 2C136A3017641106004C7401 /* main.m */, 110 | 2C136A3217641106004C7401 /* ExampleApp-OSX-Prefix.pch */, 111 | 2C136A3317641106004C7401 /* Credits.rtf */, 112 | ); 113 | name = "Supporting Files"; 114 | sourceTree = ""; 115 | }; 116 | 2C1562C1176BA9FF00B4AE50 /* WebViewJavascriptBridge */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | EF5DC17423474A0A00F81F96 /* WKWebView+JavaScriptBridge.h */, 120 | EF5DC17523474A0A00F81F96 /* WKWebView+JavaScriptBridge.m */, 121 | ); 122 | name = WebViewJavascriptBridge; 123 | path = ../../WebViewJavascriptBridge; 124 | sourceTree = ""; 125 | }; 126 | /* End PBXGroup section */ 127 | 128 | /* Begin PBXNativeTarget section */ 129 | 2C136A2017641106004C7401 /* ExampleApp-OSX */ = { 130 | isa = PBXNativeTarget; 131 | buildConfigurationList = 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */; 132 | buildPhases = ( 133 | 2C136A1D17641106004C7401 /* Sources */, 134 | 2C136A1E17641106004C7401 /* Frameworks */, 135 | 2C136A1F17641106004C7401 /* Resources */, 136 | ); 137 | buildRules = ( 138 | ); 139 | dependencies = ( 140 | ); 141 | name = "ExampleApp-OSX"; 142 | productName = "ExampleApp-OSX"; 143 | productReference = 2C136A2117641106004C7401 /* ExampleApp-OSX.app */; 144 | productType = "com.apple.product-type.application"; 145 | }; 146 | /* End PBXNativeTarget section */ 147 | 148 | /* Begin PBXProject section */ 149 | 2C136A1917641106004C7401 /* Project object */ = { 150 | isa = PBXProject; 151 | attributes = { 152 | LastUpgradeCheck = 0810; 153 | ORGANIZATIONNAME = "Marcus Westin"; 154 | }; 155 | buildConfigurationList = 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */; 156 | compatibilityVersion = "Xcode 3.2"; 157 | developmentRegion = English; 158 | hasScannedForEncodings = 0; 159 | knownRegions = ( 160 | English, 161 | en, 162 | ); 163 | mainGroup = 2C136A1817641106004C7401; 164 | productRefGroup = 2C136A2217641106004C7401 /* Products */; 165 | projectDirPath = ""; 166 | projectRoot = ""; 167 | targets = ( 168 | 2C136A2017641106004C7401 /* ExampleApp-OSX */, 169 | ); 170 | }; 171 | /* End PBXProject section */ 172 | 173 | /* Begin PBXResourcesBuildPhase section */ 174 | 2C136A1F17641106004C7401 /* Resources */ = { 175 | isa = PBXResourcesBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | 2C136A2F17641106004C7401 /* InfoPlist.strings in Resources */, 179 | 2C136A3517641106004C7401 /* Credits.rtf in Resources */, 180 | 2C136A5A17642704004C7401 /* ExampleApp.html in Resources */, 181 | 2CF17F5317D8AACF006E828B /* MainMenu.xib in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXSourcesBuildPhase section */ 188 | 2C136A1D17641106004C7401 /* Sources */ = { 189 | isa = PBXSourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | EF5DC17623474A0A00F81F96 /* WKWebView+JavaScriptBridge.m in Sources */, 193 | 2C136A3117641106004C7401 /* main.m in Sources */, 194 | 2C136A3817641106004C7401 /* AppDelegate.m in Sources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXSourcesBuildPhase section */ 199 | 200 | /* Begin PBXVariantGroup section */ 201 | 2C136A2D17641106004C7401 /* InfoPlist.strings */ = { 202 | isa = PBXVariantGroup; 203 | children = ( 204 | 2C136A2E17641106004C7401 /* en */, 205 | ); 206 | name = InfoPlist.strings; 207 | sourceTree = ""; 208 | }; 209 | 2C136A3317641106004C7401 /* Credits.rtf */ = { 210 | isa = PBXVariantGroup; 211 | children = ( 212 | 2C136A3417641106004C7401 /* en */, 213 | ); 214 | name = Credits.rtf; 215 | sourceTree = ""; 216 | }; 217 | /* End PBXVariantGroup section */ 218 | 219 | /* Begin XCBuildConfiguration section */ 220 | 2C136A3C17641106004C7401 /* Debug */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | ALWAYS_SEARCH_USER_PATHS = NO; 224 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 225 | CLANG_CXX_LIBRARY = "libc++"; 226 | CLANG_ENABLE_OBJC_ARC = YES; 227 | CLANG_WARN_BOOL_CONVERSION = YES; 228 | CLANG_WARN_CONSTANT_CONVERSION = YES; 229 | CLANG_WARN_EMPTY_BODY = YES; 230 | CLANG_WARN_ENUM_CONVERSION = YES; 231 | CLANG_WARN_INFINITE_RECURSION = YES; 232 | CLANG_WARN_INT_CONVERSION = YES; 233 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 234 | CLANG_WARN_UNREACHABLE_CODE = YES; 235 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 236 | COPY_PHASE_STRIP = NO; 237 | ENABLE_STRICT_OBJC_MSGSEND = YES; 238 | ENABLE_TESTABILITY = YES; 239 | GCC_C_LANGUAGE_STANDARD = gnu99; 240 | GCC_DYNAMIC_NO_PIC = NO; 241 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 242 | GCC_NO_COMMON_BLOCKS = YES; 243 | GCC_OPTIMIZATION_LEVEL = 0; 244 | GCC_PREPROCESSOR_DEFINITIONS = ( 245 | "DEBUG=1", 246 | "$(inherited)", 247 | ); 248 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | MACOSX_DEPLOYMENT_TARGET = 10.8; 256 | ONLY_ACTIVE_ARCH = YES; 257 | SDKROOT = macosx; 258 | }; 259 | name = Debug; 260 | }; 261 | 2C136A3D17641106004C7401 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_OBJC_ARC = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | COPY_PHASE_STRIP = YES; 278 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu99; 281 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 282 | GCC_NO_COMMON_BLOCKS = YES; 283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 284 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 285 | GCC_WARN_UNDECLARED_SELECTOR = YES; 286 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 287 | GCC_WARN_UNUSED_FUNCTION = YES; 288 | GCC_WARN_UNUSED_VARIABLE = YES; 289 | MACOSX_DEPLOYMENT_TARGET = 10.8; 290 | SDKROOT = macosx; 291 | }; 292 | name = Release; 293 | }; 294 | 2C136A3F17641106004C7401 /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | COMBINE_HIDPI_IMAGES = YES; 298 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 299 | GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; 300 | INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; 301 | MACOSX_DEPLOYMENT_TARGET = 10.7; 302 | PRODUCT_BUNDLE_IDENTIFIER = "WebViewJavascriptBridge.$(PRODUCT_NAME:rfc1034identifier)"; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | WRAPPER_EXTENSION = app; 305 | }; 306 | name = Debug; 307 | }; 308 | 2C136A4017641106004C7401 /* Release */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | COMBINE_HIDPI_IMAGES = YES; 312 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 313 | GCC_PREFIX_HEADER = "ExampleApp-OSX/ExampleApp-OSX-Prefix.pch"; 314 | INFOPLIST_FILE = "ExampleApp-OSX/ExampleApp-OSX-Info.plist"; 315 | MACOSX_DEPLOYMENT_TARGET = 10.7; 316 | PRODUCT_BUNDLE_IDENTIFIER = "WebViewJavascriptBridge.$(PRODUCT_NAME:rfc1034identifier)"; 317 | PRODUCT_NAME = "$(TARGET_NAME)"; 318 | WRAPPER_EXTENSION = app; 319 | }; 320 | name = Release; 321 | }; 322 | /* End XCBuildConfiguration section */ 323 | 324 | /* Begin XCConfigurationList section */ 325 | 2C136A1C17641106004C7401 /* Build configuration list for PBXProject "ExampleApp-OSX" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | 2C136A3C17641106004C7401 /* Debug */, 329 | 2C136A3D17641106004C7401 /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | 2C136A3E17641106004C7401 /* Build configuration list for PBXNativeTarget "ExampleApp-OSX" */ = { 335 | isa = XCConfigurationList; 336 | buildConfigurations = ( 337 | 2C136A3F17641106004C7401 /* Debug */, 338 | 2C136A4017641106004C7401 /* Release */, 339 | ); 340 | defaultConfigurationIsVisible = 0; 341 | defaultConfigurationName = Release; 342 | }; 343 | /* End XCConfigurationList section */ 344 | }; 345 | rootObject = 2C136A1917641106004C7401 /* Project object */; 346 | } 347 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ExampleApp-OSX 4 | // 5 | // Created by Marcus Westin on 6/8/13. 6 | // Copyright (c) 2013 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ExampleApp-OSX 4 | // 5 | // Created by Marcus Westin on 6/8/13. 6 | // Copyright (c) 2013 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | #import "WKWebView+JavaScriptBridge.h" 12 | 13 | @implementation AppDelegate { 14 | WKWebView *_WKWebView; 15 | NSView* _WKWebViewWrapper; 16 | } 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 19 | { 20 | [self _createViews]; 21 | [self _configureWKWebview]; 22 | } 23 | 24 | - (void)_configureWKWebview { 25 | // Create Bridge 26 | [WKWebView enableLogging:LogginglevelAll]; 27 | [_WKWebView registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { 28 | NSLog(@"testObjcCallback called: %@", data); 29 | responseCallback(@"Response from testObjcCallback"); 30 | }]; 31 | 32 | // Create Buttons 33 | NSButton *callbackButton = [[NSButton alloc] initWithFrame:NSMakeRect(5, 0, 120, 40)]; 34 | [callbackButton setTitle:@"Call handler"]; 35 | [callbackButton setBezelStyle:NSRoundedBezelStyle]; 36 | [callbackButton setTarget:self]; 37 | [callbackButton setAction:@selector(_WKCallHandler)]; 38 | [_WKWebView addSubview:callbackButton]; 39 | 40 | 41 | // Load Page 42 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; 43 | NSString* html = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; 44 | NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; 45 | [_WKWebView loadHTMLString:html baseURL:baseURL]; 46 | } 47 | - (void)_WKCallHandler { 48 | id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; 49 | [_WKWebView callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { 50 | NSLog(@"testJavascriptHandler responded: %@", response); 51 | }]; 52 | } 53 | 54 | - (void)_createViews { 55 | NSView* contentView = _window.contentView; 56 | // WKWebView 57 | WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; 58 | _WKWebView = [[WKWebView alloc] initWithFrame:contentView.frame configuration:config]; 59 | [_WKWebView setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; 60 | 61 | [contentView addSubview:_WKWebView]; 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/ExampleApp-OSX-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Marcus Westin. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/ExampleApp-OSX-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ExampleApp-OSX' target in the 'ExampleApp-OSX' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-OSX/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ExampleApp-OSX 4 | // 5 | // Created by Marcus Westin on 6/8/13. 6 | // Copyright (c) 2013 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0E4E9D4C1A101E0B00043087 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8082DC19EDD98700479452 /* WebKit.framework */; }; 11 | 0ECB01441A0EE1F20037FF4E /* ExampleWKWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */; }; 12 | 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CA045B717117439006DEE8B /* InfoPlist.strings */; }; 13 | 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */; }; 14 | 2CA045C317117439006DEE8B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA045BE17117439006DEE8B /* main.m */; }; 15 | 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */; }; 16 | 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */; }; 17 | 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2CEB3EBF1602563600548120 /* UIKit.framework */; }; 18 | EF5D0B3224599757008DC69C /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */; }; 19 | EF5D0B3324599757008DC69C /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */; }; 20 | EF5D0B3424599757008DC69C /* WebViewJavascriptLeakAvoider.m in Sources */ = {isa = PBXBuildFile; fileRef = EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */; }; 21 | EFE398AF242C348C0027857D /* TestConsole.html in Resources */ = {isa = PBXBuildFile; fileRef = EFE398AE242C348C0027857D /* TestConsole.html */; }; 22 | EFF05EC5244C0FED0060F71C /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EFF05EC4244C0FED0060F71C /* FirstViewController.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 0E8082DC19EDD98700479452 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 27 | 0ECB01421A0EE1BA0037FF4E /* ExampleWKWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleWKWebViewController.h; sourceTree = ""; }; 28 | 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleWKWebViewController.m; sourceTree = ""; }; 29 | 2CA045B817117439006DEE8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ExampleApp-iOS-Info.plist"; sourceTree = ""; }; 31 | 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ExampleApp-iOS-Prefix.pch"; sourceTree = ""; }; 32 | 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleAppDelegate.h; sourceTree = ""; }; 33 | 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleAppDelegate.m; sourceTree = ""; }; 34 | 2CA045BE17117439006DEE8B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 35 | 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = SOURCE_ROOT; }; 36 | 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "ExampleApp-iOS/Default-568h@2x.png"; sourceTree = ""; }; 37 | 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ExampleApp-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 2CEB3EBF1602563600548120 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 39 | 2CEB3EC11602563600548120 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 40 | 2CEB3EC31602563600548120 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 41 | EF5D0B2C24599756008DC69C /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 42 | EF5D0B2D24599756008DC69C /* WebViewJavascriptLeakAvoider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptLeakAvoider.h; sourceTree = ""; }; 43 | EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 44 | EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; 45 | EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptLeakAvoider.m; sourceTree = ""; }; 46 | EF5D0B3124599757008DC69C /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; 47 | EFE398AE242C348C0027857D /* TestConsole.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = TestConsole.html; sourceTree = SOURCE_ROOT; }; 48 | EFF05EC3244C0FED0060F71C /* FirstViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = ""; }; 49 | EFF05EC4244C0FED0060F71C /* FirstViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 2CEB3EB81602563600548120 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | 0E4E9D4C1A101E0B00043087 /* WebKit.framework in Frameworks */, 58 | 2CEB3EC01602563600548120 /* UIKit.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | EF5D0B2C24599756008DC69C /* WebViewJavascriptBridge.h */, 69 | EF5D0B2E24599756008DC69C /* WebViewJavascriptBridge.m */, 70 | EF5D0B3124599757008DC69C /* WebViewJavascriptBridgeBase.h */, 71 | EF5D0B2F24599756008DC69C /* WebViewJavascriptBridgeBase.m */, 72 | EF5D0B2D24599756008DC69C /* WebViewJavascriptLeakAvoider.h */, 73 | EF5D0B3024599757008DC69C /* WebViewJavascriptLeakAvoider.m */, 74 | ); 75 | name = WebViewJavascriptBridge; 76 | path = ../../WebViewJavascriptBridge; 77 | sourceTree = ""; 78 | }; 79 | 2CA045B617117439006DEE8B /* ExampleApp-iOS */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 2CA0465B1711AC8D006DEE8B /* ExampleApp.html */, 83 | EFE398AE242C348C0027857D /* TestConsole.html */, 84 | 2CA045BC17117439006DEE8B /* ExampleAppDelegate.h */, 85 | 2CA045BD17117439006DEE8B /* ExampleAppDelegate.m */, 86 | EFF05EC3244C0FED0060F71C /* FirstViewController.h */, 87 | EFF05EC4244C0FED0060F71C /* FirstViewController.m */, 88 | 0ECB01421A0EE1BA0037FF4E /* ExampleWKWebViewController.h */, 89 | 0ECB01431A0EE1F20037FF4E /* ExampleWKWebViewController.m */, 90 | 2C1562A7176B9F5400B4AE50 /* WebViewJavascriptBridge */, 91 | 2CA046211711A94E006DEE8B /* Supporting Files */, 92 | ); 93 | path = "ExampleApp-iOS"; 94 | sourceTree = ""; 95 | }; 96 | 2CA046211711A94E006DEE8B /* Supporting Files */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 2CA045B717117439006DEE8B /* InfoPlist.strings */, 100 | 2CA045B917117439006DEE8B /* ExampleApp-iOS-Info.plist */, 101 | 2CA045BA17117439006DEE8B /* ExampleApp-iOS-Prefix.pch */, 102 | 2CA045BE17117439006DEE8B /* main.m */, 103 | ); 104 | name = "Supporting Files"; 105 | sourceTree = ""; 106 | }; 107 | 2CEB3EB01602563600548120 = { 108 | isa = PBXGroup; 109 | children = ( 110 | 2CAB869A1727684300BD9ED1 /* Default-568h@2x.png */, 111 | 2CA045B617117439006DEE8B /* ExampleApp-iOS */, 112 | 2CEB3EBE1602563600548120 /* Frameworks */, 113 | 2CEB3EBC1602563600548120 /* Products */, 114 | 81A733051B2F9C5795D856E4 /* Pods */, 115 | ); 116 | sourceTree = ""; 117 | }; 118 | 2CEB3EBC1602563600548120 /* Products */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | 2CEB3EBE1602563600548120 /* Frameworks */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 0E8082DC19EDD98700479452 /* WebKit.framework */, 130 | 2CEB3EBF1602563600548120 /* UIKit.framework */, 131 | 2CEB3EC11602563600548120 /* Foundation.framework */, 132 | 2CEB3EC31602563600548120 /* CoreGraphics.framework */, 133 | ); 134 | name = Frameworks; 135 | sourceTree = ""; 136 | }; 137 | 81A733051B2F9C5795D856E4 /* Pods */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | ); 141 | name = Pods; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | 2CEB3EBA1602563600548120 /* ExampleApp-iOS */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp-iOS" */; 150 | buildPhases = ( 151 | 2CEB3EB71602563600548120 /* Sources */, 152 | 2CEB3EB81602563600548120 /* Frameworks */, 153 | 2CEB3EB91602563600548120 /* Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = "ExampleApp-iOS"; 160 | productName = ExampleApp; 161 | productReference = 2CEB3EBB1602563600548120 /* ExampleApp-iOS.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | 2CEB3EB21602563600548120 /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | LastUpgradeCheck = 0810; 171 | ORGANIZATIONNAME = "Marcus Westin"; 172 | TargetAttributes = { 173 | 2CEB3EBA1602563600548120 = { 174 | DevelopmentTeam = D9DMY5ZV46; 175 | LastSwiftMigration = 0820; 176 | }; 177 | }; 178 | }; 179 | buildConfigurationList = 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp-iOS" */; 180 | compatibilityVersion = "Xcode 3.2"; 181 | developmentRegion = English; 182 | hasScannedForEncodings = 0; 183 | knownRegions = ( 184 | English, 185 | en, 186 | ); 187 | mainGroup = 2CEB3EB01602563600548120; 188 | productRefGroup = 2CEB3EBC1602563600548120 /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 2CEB3EBA1602563600548120 /* ExampleApp-iOS */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | 2CEB3EB91602563600548120 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 2CA045BF17117439006DEE8B /* InfoPlist.strings in Resources */, 203 | 2CA0465C1711AC8E006DEE8B /* ExampleApp.html in Resources */, 204 | EFE398AF242C348C0027857D /* TestConsole.html in Resources */, 205 | 2CAB869B1727684300BD9ED1 /* Default-568h@2x.png in Resources */, 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | /* End PBXResourcesBuildPhase section */ 210 | 211 | /* Begin PBXSourcesBuildPhase section */ 212 | 2CEB3EB71602563600548120 /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 0ECB01441A0EE1F20037FF4E /* ExampleWKWebViewController.m in Sources */, 217 | EFF05EC5244C0FED0060F71C /* FirstViewController.m in Sources */, 218 | EF5D0B3424599757008DC69C /* WebViewJavascriptLeakAvoider.m in Sources */, 219 | 2CA045C217117439006DEE8B /* ExampleAppDelegate.m in Sources */, 220 | 2CA045C317117439006DEE8B /* main.m in Sources */, 221 | EF5D0B3324599757008DC69C /* WebViewJavascriptBridgeBase.m in Sources */, 222 | EF5D0B3224599757008DC69C /* WebViewJavascriptBridge.m in Sources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXSourcesBuildPhase section */ 227 | 228 | /* Begin PBXVariantGroup section */ 229 | 2CA045B717117439006DEE8B /* InfoPlist.strings */ = { 230 | isa = PBXVariantGroup; 231 | children = ( 232 | 2CA045B817117439006DEE8B /* en */, 233 | ); 234 | name = InfoPlist.strings; 235 | sourceTree = ""; 236 | }; 237 | /* End PBXVariantGroup section */ 238 | 239 | /* Begin XCBuildConfiguration section */ 240 | 2CEB3ED11602563600548120 /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_OBJC_ARC = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_CONSTANT_CONVERSION = YES; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 254 | CLANG_WARN_UNREACHABLE_CODE = YES; 255 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 256 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 257 | COPY_PHASE_STRIP = NO; 258 | ENABLE_STRICT_OBJC_MSGSEND = YES; 259 | ENABLE_TESTABILITY = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu99; 261 | GCC_DYNAMIC_NO_PIC = NO; 262 | GCC_NO_COMMON_BLOCKS = YES; 263 | GCC_OPTIMIZATION_LEVEL = 0; 264 | GCC_PREPROCESSOR_DEFINITIONS = ( 265 | "DEBUG=1", 266 | "$(inherited)", 267 | ); 268 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 276 | ONLY_ACTIVE_ARCH = YES; 277 | SDKROOT = iphoneos; 278 | }; 279 | name = Debug; 280 | }; 281 | 2CEB3ED21602563600548120 /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ALWAYS_SEARCH_USER_PATHS = NO; 285 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 286 | CLANG_CXX_LIBRARY = "libc++"; 287 | CLANG_ENABLE_OBJC_ARC = YES; 288 | CLANG_WARN_BOOL_CONVERSION = YES; 289 | CLANG_WARN_CONSTANT_CONVERSION = YES; 290 | CLANG_WARN_EMPTY_BODY = YES; 291 | CLANG_WARN_ENUM_CONVERSION = YES; 292 | CLANG_WARN_INFINITE_RECURSION = YES; 293 | CLANG_WARN_INT_CONVERSION = YES; 294 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 295 | CLANG_WARN_UNREACHABLE_CODE = YES; 296 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 297 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 298 | COPY_PHASE_STRIP = YES; 299 | ENABLE_STRICT_OBJC_MSGSEND = YES; 300 | GCC_C_LANGUAGE_STANDARD = gnu99; 301 | GCC_NO_COMMON_BLOCKS = YES; 302 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 303 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 304 | GCC_WARN_UNDECLARED_SELECTOR = YES; 305 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 306 | GCC_WARN_UNUSED_FUNCTION = YES; 307 | GCC_WARN_UNUSED_VARIABLE = YES; 308 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 309 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 310 | SDKROOT = iphoneos; 311 | VALIDATE_PRODUCT = YES; 312 | }; 313 | name = Release; 314 | }; 315 | 2CEB3ED41602563600548120 /* Debug */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | CLANG_ENABLE_MODULES = YES; 319 | DEVELOPMENT_TEAM = D9DMY5ZV46; 320 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 321 | GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch"; 322 | INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist"; 323 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 324 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 325 | PRODUCT_BUNDLE_IDENTIFIER = "com.example.${PRODUCT_NAME:rfc1034identifier}"; 326 | PRODUCT_NAME = "ExampleApp-iOS"; 327 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 328 | SWIFT_VERSION = 3.0; 329 | WRAPPER_EXTENSION = app; 330 | }; 331 | name = Debug; 332 | }; 333 | 2CEB3ED51602563600548120 /* Release */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | CLANG_ENABLE_MODULES = YES; 337 | DEVELOPMENT_TEAM = D9DMY5ZV46; 338 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 339 | GCC_PREFIX_HEADER = "ExampleApp-iOS/ExampleApp-iOS-Prefix.pch"; 340 | INFOPLIST_FILE = "ExampleApp-iOS/ExampleApp-iOS-Info.plist"; 341 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 342 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 343 | PRODUCT_BUNDLE_IDENTIFIER = "com.example.${PRODUCT_NAME:rfc1034identifier}"; 344 | PRODUCT_NAME = "ExampleApp-iOS"; 345 | SWIFT_VERSION = 3.0; 346 | WRAPPER_EXTENSION = app; 347 | }; 348 | name = Release; 349 | }; 350 | /* End XCBuildConfiguration section */ 351 | 352 | /* Begin XCConfigurationList section */ 353 | 2CEB3EB51602563600548120 /* Build configuration list for PBXProject "ExampleApp-iOS" */ = { 354 | isa = XCConfigurationList; 355 | buildConfigurations = ( 356 | 2CEB3ED11602563600548120 /* Debug */, 357 | 2CEB3ED21602563600548120 /* Release */, 358 | ); 359 | defaultConfigurationIsVisible = 0; 360 | defaultConfigurationName = Release; 361 | }; 362 | 2CEB3ED31602563600548120 /* Build configuration list for PBXNativeTarget "ExampleApp-iOS" */ = { 363 | isa = XCConfigurationList; 364 | buildConfigurations = ( 365 | 2CEB3ED41602563600548120 /* Debug */, 366 | 2CEB3ED51602563600548120 /* Release */, 367 | ); 368 | defaultConfigurationIsVisible = 0; 369 | defaultConfigurationName = Release; 370 | }; 371 | /* End XCConfigurationList section */ 372 | }; 373 | rootObject = 2CEB3EB21602563600548120 /* Project object */; 374 | } 375 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS.xcodeproj/xcshareddata/xcschemes/ExampleApp-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/housenkui/WebViewJavascriptBridge/63ef08930ffcf62c3854cc1dd2e8b9fec43202aa/Example Apps/ExampleApp-iOS/Default-568h@2x.png -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleApp-iOS-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleApp-iOS-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ExampleApp' target in the 'ExampleApp' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ExampleAppDelegate : UIResponder 4 | @property (nonatomic) UIWindow *window; 5 | @end 6 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "ExampleAppDelegate.h" 2 | #import "ExampleWKWebViewController.h" 3 | #import "FirstViewController.h" 4 | 5 | @implementation ExampleAppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | 9 | UITabBarController *tabBarController = [[UITabBarController alloc] init]; 10 | 11 | ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; 12 | WKWebViewExampleController.tabBarItem.title = @"WKWebView"; 13 | [tabBarController addChildViewController:WKWebViewExampleController]; 14 | 15 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 16 | 17 | UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[FirstViewController new]]; 18 | self.window.rootViewController = nav; 19 | [self.window makeKeyAndVisible]; 20 | 21 | return YES; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleWKWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWKWebViewController.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 1/13/14. 6 | // Copyright (c) 2014 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ExampleWKWebViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/ExampleWKWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWKWebViewController.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 1/13/14. 6 | // Copyright (c) 2014 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "ExampleWKWebViewController.h" 10 | #import "WebViewJavascriptBridge.h" 11 | @interface ExampleWKWebViewController () 12 | @property (nonatomic, strong) WKWebView *webView; 13 | @property (nonatomic, strong) WebViewJavascriptBridge* bridge; 14 | @end 15 | 16 | @implementation ExampleWKWebViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; 22 | [self.view addSubview:self.webView]; 23 | 24 | _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView 25 | showJSconsole:YES 26 | enableLogging:YES]; 27 | 28 | [_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) { 29 | NSLog(@"testObjcCallback called: %@", data); 30 | responseCallback(@"Response from testObjcCallback111"); 31 | }]; 32 | [self renderButtons:self.webView]; 33 | [self loadExamplePage:self.webView]; 34 | 35 | } 36 | 37 | - (void)renderButtons:(WKWebView*)webView { 38 | UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0]; 39 | 40 | UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 41 | [callbackButton setTitle:@"Call handler" forState:UIControlStateNormal]; 42 | [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside]; 43 | [self.view insertSubview:callbackButton aboveSubview:webView]; 44 | callbackButton.frame = CGRectMake(10, 400, 100, 35); 45 | callbackButton.titleLabel.font = font; 46 | 47 | UIButton* reloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 48 | [reloadButton setTitle:@"Reload webview" forState:UIControlStateNormal]; 49 | [reloadButton addTarget:webView action:@selector(reload) forControlEvents:UIControlEventTouchUpInside]; 50 | [self.view insertSubview:reloadButton aboveSubview:webView]; 51 | reloadButton.frame = CGRectMake(110, 400, 100, 35); 52 | reloadButton.titleLabel.font = font; 53 | 54 | } 55 | 56 | - (void)callHandler:(id)sender { 57 | id data = @{ @"greetingFromObjC": @"Hi there, JS!" }; 58 | [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) { 59 | NSLog(@"testJavascriptHandler responded: %@", response); 60 | }]; 61 | } 62 | 63 | - (void)loadExamplePage:(WKWebView*)webView { 64 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; 65 | NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; 66 | NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; 67 | [webView loadHTMLString:appHtml baseURL:baseURL]; 68 | } 69 | - (WKWebView *) webView { 70 | if (!_webView) { 71 | WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; 72 | _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; 73 | [self.view addSubview:_webView]; 74 | 75 | } 76 | return _webView; 77 | } 78 | 79 | -(void)viewDidDisappear:(BOOL)animated { 80 | [super viewDidDisappear:animated]; 81 | 82 | NSLog(@"viewDidDisappear``"); 83 | [self.webView.configuration.userContentController removeAllUserScripts]; 84 | } 85 | @end 86 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/FirstViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/19. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface FirstViewController : UIViewController 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/FirstViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/19. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "FirstViewController.h" 10 | #import "ExampleWKWebViewController.h" 11 | @interface FirstViewController () 12 | 13 | @end 14 | 15 | @implementation FirstViewController 16 | 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.title = @"first page"; 21 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 22 | [button setTitle:@"click me" forState:UIControlStateNormal]; 23 | [button addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside]; 24 | button.frame = CGRectMake(100, 200, 100, 40); 25 | button.center = self.view.center; 26 | self.view.backgroundColor = [UIColor redColor]; 27 | [self.view addSubview:button]; 28 | // Do any additional setup after loading the view. 29 | } 30 | - (void)jump{ 31 | // UITabBarController *tabBarController = [[UITabBarController alloc] init]; 32 | 33 | ExampleWKWebViewController* WKWebViewExampleController = [[ExampleWKWebViewController alloc] init]; 34 | // WKWebViewExampleController.tabBarItem.title = @"WKWebView"; 35 | // [tabBarController addChildViewController:WKWebViewExampleController]; 36 | // [self presentViewController:WKWebViewExampleController animated:YES completion:nil]; 37 | [self.navigationController pushViewController:WKWebViewExampleController animated:YES]; 38 | } 39 | /* 40 | #pragma mark - Navigation 41 | 42 | // In a storyboard-based application, you will often want to do a little preparation before navigation 43 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 44 | // Get the new view controller using [segue destinationViewController]. 45 | // Pass the selected object to the new view controller. 46 | } 47 | */ 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example Apps/ExampleApp-iOS/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import "ExampleAppDelegate.h" 5 | 6 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) 7 | 8 | int main(int argc, char * argv[]) 9 | { 10 | @autoreleasepool { 11 | // Dynamically load WebKit if iOS version >= 8 12 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { 13 | #if TARGET_IPHONE_SIMULATOR 14 | NSString *frameworkPath = [[NSProcessInfo processInfo] environment][@"DYLD_FALLBACK_FRAMEWORK_PATH"]; 15 | if (frameworkPath) { 16 | NSString *webkitLibraryPath = [NSString pathWithComponents:@[frameworkPath, @"WebKit.framework", @"WebKit"]]; 17 | dlopen([webkitLibraryPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_LAZY); 18 | } 19 | #else 20 | dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", RTLD_LAZY); 21 | #endif 22 | } 23 | 24 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ExampleAppDelegate class])); 25 | } 26 | } -------------------------------------------------------------------------------- /Example Apps/ExampleApp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 |

WebViewJavascriptBridge Demo

12 | 13 | 73 |
74 | 75 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ExampleSwiftApp-iOS 4 | // 5 | // Created by John Marcus Westin on 12/27/16. 6 | // Copyright © 2016 Marcus Westin. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import WebViewJavascriptBridge 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | // Override point for customization after application launch. 20 | return true 21 | } 22 | 23 | func applicationWillResignActive(_ application: UIApplication) { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 26 | } 27 | 28 | func applicationDidEnterBackground(_ application: UIApplication) { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | func applicationWillEnterForeground(_ application: UIApplication) { 34 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | func applicationDidBecomeActive(_ application: UIApplication) { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | func applicationWillTerminate(_ application: UIApplication) { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ExampleSwiftApp-iOS 4 | // 5 | // Created by John Marcus Westin on 12/27/16. 6 | // Copyright © 2016 Marcus Westin. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOSTests/ExampleSwiftApp_iOSTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleSwiftApp_iOSTests.swift 3 | // ExampleSwiftApp-iOSTests 4 | // 5 | // Created by John Marcus Westin on 12/27/16. 6 | // Copyright © 2016 Marcus Westin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import WebKit 11 | 12 | import WebViewJavascriptBridge 13 | @testable import ExampleSwiftApp_iOS 14 | 15 | let timeout: Double = 3 16 | 17 | class ExampleSwiftApp_iOSTests: XCTestCase { 18 | var uiWebView: UIWebView = UIWebView.init() 19 | var wkWebView: WKWebView = WKWebView.init() 20 | var bridgeRefs: NSMutableArray = [] 21 | 22 | override func setUp() { 23 | super.setUp() 24 | 25 | let rootVC = (UIApplication.shared.delegate as! AppDelegate).window!.rootViewController! 26 | var frame = rootVC.view.bounds 27 | frame.size.height /= 2 28 | 29 | uiWebView = UIWebView.init(frame: frame) 30 | uiWebView.backgroundColor = UIColor.blue 31 | rootVC.view.addSubview(uiWebView) 32 | 33 | frame.origin.y += frame.size.height 34 | wkWebView = WKWebView.init(frame: frame) 35 | wkWebView.backgroundColor = UIColor.red 36 | rootVC.view.addSubview(wkWebView) 37 | 38 | bridgeRefs = NSMutableArray.init() 39 | } 40 | 41 | override func tearDown() { 42 | super.tearDown() 43 | uiWebView.removeFromSuperview() 44 | wkWebView.removeFromSuperview() 45 | } 46 | 47 | func bridgeForWebView(_ webView: Any) -> WebViewJavascriptBridge { 48 | let bridge = WebViewJavascriptBridge.init(webView)! 49 | bridgeRefs.add(bridge) 50 | return bridge 51 | } 52 | 53 | func loadEchoSample(_ webView: Any) { 54 | let request = URLRequest.init(url: Bundle.main.url(forResource: "echo", withExtension: "html")!) 55 | if webView is UIWebView { 56 | (webView as! UIWebView).loadRequest(request) 57 | } else { 58 | (webView as! WKWebView).load(request) 59 | } 60 | } 61 | 62 | func testSetup() { 63 | _testSetup(webView: uiWebView) 64 | _testSetup(webView: wkWebView) 65 | waitForExpectations(timeout: timeout, handler: nil) 66 | } 67 | func _testSetup(webView: Any) { 68 | let setup = self.expectation(description: "Setup completed") 69 | let bridge = self.bridgeForWebView(webView) 70 | bridge.registerHandler("Greet") { (data, responseCallback) in 71 | XCTAssertEqual(data as! String, "Hello world") 72 | setup.fulfill() 73 | } 74 | XCTAssertNotNil(bridge) 75 | self.loadEchoSample(webView) 76 | } 77 | 78 | 79 | func testEchoHandler() { 80 | _testEchoHandler(uiWebView) 81 | _testEchoHandler(wkWebView) 82 | waitForExpectations(timeout: timeout, handler: nil) 83 | } 84 | func _testEchoHandler(_ webView: Any) { 85 | let bridge = bridgeForWebView(webView) 86 | 87 | let callbackInvoked = expectation(description: "Callback invoked") 88 | bridge.callHandler("echoHandler", data:"testEchoHandler") { (responseData) in 89 | XCTAssertEqual(responseData as! String, "testEchoHandler"); 90 | callbackInvoked.fulfill() 91 | }; 92 | 93 | loadEchoSample(webView); 94 | } 95 | 96 | func testEchoHandlerAfterSetup() { 97 | _testEchoHandlerAfterSetup(uiWebView) 98 | _testEchoHandlerAfterSetup(wkWebView) 99 | waitForExpectations(timeout: timeout, handler: nil) 100 | } 101 | func _testEchoHandlerAfterSetup(_ webView: Any) { 102 | let bridge = bridgeForWebView(webView) 103 | 104 | let callbackInvoked = expectation(description: "Callback invoked") 105 | loadEchoSample(webView); 106 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.150) { 107 | bridge.callHandler("echoHandler", data:"testEchoHandler") { (responseData) in 108 | XCTAssertEqual(responseData as! String, "testEchoHandler") 109 | callbackInvoked.fulfill() 110 | } 111 | } 112 | } 113 | 114 | func testObjectEncoding() { 115 | _testObjectEncoding(uiWebView) 116 | _testObjectEncoding(wkWebView) 117 | waitForExpectations(timeout: timeout, handler: nil) 118 | } 119 | func _testObjectEncoding(_ webView: Any) { 120 | let bridge = bridgeForWebView(webView) 121 | 122 | func echoObject(_ object: Any) { 123 | let callbackInvoked = expectation(description: "Callback invoked") 124 | bridge.callHandler("echoHandler", data:object) { (responseData) in 125 | if (object is NSDictionary) { 126 | XCTAssertEqual(responseData as! NSDictionary, object as! NSDictionary) 127 | } else if (object is NSArray) { 128 | XCTAssertEqual(responseData as! NSArray, object as! NSArray) 129 | } 130 | callbackInvoked.fulfill() 131 | } 132 | } 133 | 134 | echoObject("A string sent over the wire"); 135 | echoObject("A string with '\"'/\\"); 136 | echoObject([1, 2, 3]); 137 | echoObject(["a":1, "b":2]); 138 | 139 | loadEchoSample(webView); 140 | } 141 | 142 | func testJavascriptReceiveResponse() { 143 | _testJavascriptReceiveResponse(uiWebView) 144 | _testJavascriptReceiveResponse(wkWebView) 145 | waitForExpectations(timeout: timeout, handler: nil) 146 | } 147 | func _testJavascriptReceiveResponse(_ webView: Any) { 148 | let bridge = bridgeForWebView(webView) 149 | loadEchoSample(webView); 150 | let callbackInvoked = expectation(description: "Callback invoked") 151 | bridge.registerHandler("objcEchoToJs") { (data, responseCallback) in 152 | XCTAssertEqual(data as! NSDictionary, ["foo":"bar"]); 153 | responseCallback!(data) 154 | } 155 | bridge.callHandler("jsRcvResponseTest", data:nil) { (responseData) in 156 | XCTAssertEqual(responseData as! String, "Response from JS"); 157 | callbackInvoked.fulfill() 158 | } 159 | } 160 | 161 | func testJavascriptReceiveResponseWithoutSafetyTimeout() { 162 | _testJavascriptReceiveResponseWithoutSafetyTimeout(uiWebView) 163 | _testJavascriptReceiveResponseWithoutSafetyTimeout(wkWebView) 164 | waitForExpectations(timeout: timeout, handler: nil) 165 | } 166 | func _testJavascriptReceiveResponseWithoutSafetyTimeout(_ webView: Any) { 167 | let bridge = bridgeForWebView(webView) 168 | bridge.disableJavscriptAlertBoxSafetyTimeout() 169 | loadEchoSample(webView); 170 | let callbackInvoked = expectation(description: "Callback invoked") 171 | bridge.registerHandler("objcEchoToJs") { (data, responseCallback) in 172 | XCTAssertEqual(data as! NSDictionary, ["foo":"bar"]); 173 | responseCallback!(data); 174 | } 175 | bridge.callHandler("jsRcvResponseTest", data:nil) { (responseData) in 176 | XCTAssertEqual(responseData as! String, "Response from JS"); 177 | callbackInvoked.fulfill() 178 | } 179 | } 180 | 181 | func testRemoveHandler() { 182 | _testRemoveHandler(uiWebView) 183 | _testRemoveHandler(wkWebView) 184 | waitForExpectations(timeout: timeout, handler: nil) 185 | } 186 | func _testRemoveHandler(_ webView: Any) { 187 | loadEchoSample(webView); 188 | let bridge = bridgeForWebView(webView) 189 | let callbackNotInvoked = expectation(description: "Callback invoked") 190 | var count = 0 191 | bridge.registerHandler("objcEchoToJs") { (data, callback) in 192 | count += 1 193 | callback!(data) 194 | } 195 | bridge.callHandler("jsRcvResponseTest", data:nil) { (responseData) in 196 | XCTAssertEqual(responseData as! String, "Response from JS"); 197 | bridge.removeHandler("objcEchoToJs") 198 | bridge.callHandler("jsRcvResponseTest", data:nil) { (responseData) in 199 | // Since we have removed the "objcEchoToJs" handler, and since the 200 | // echo.html javascript won't call the response callback until it has 201 | // received a response from "objcEchoToJs", we should never get here 202 | XCTAssert(false) 203 | } 204 | bridge.callHandler("echoHandler", data:nil ) { (responseData) in 205 | XCTAssertEqual(count, 1) 206 | callbackNotInvoked.fulfill() 207 | } 208 | } 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Podfile: -------------------------------------------------------------------------------- 1 | project 'ExampleSwiftApp-iOS.xcodeproj' 2 | 3 | # Uncomment the next line to define a global platform for your project 4 | platform :ios, '9.0' 5 | use_frameworks! 6 | 7 | target 'ExampleSwiftApp-iOS' do 8 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 9 | 10 | pod 'WebViewJavascriptBridge', :path => '../..' 11 | 12 | target 'ExampleSwiftApp-iOSTests' do 13 | inherit! :search_paths 14 | 15 | pod 'WebViewJavascriptBridge', :path => '../..' 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - WebViewJavascriptBridge (6.0.2) 3 | 4 | DEPENDENCIES: 5 | - WebViewJavascriptBridge (from `../..`) 6 | 7 | EXTERNAL SOURCES: 8 | WebViewJavascriptBridge: 9 | :path: ../.. 10 | 11 | SPEC CHECKSUMS: 12 | WebViewJavascriptBridge: 791ee0e26d1bf15efe5fb7fb9666a71a19b89d77 13 | 14 | PODFILE CHECKSUM: f657cfcc5a24b7c7f0c7781719b73d4a834bc276 15 | 16 | COCOAPODS: 1.1.1 17 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Local Podspecs/WebViewJavascriptBridge.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebViewJavascriptBridge", 3 | "version": "6.0.2", 4 | "summary": "An iOS & OSX bridge for sending messages between Obj-C/Swift and JavaScript in WKWebViews, UIWebViews & WebViews.", 5 | "homepage": "https://github.com/marcuswestin/WebViewJavascriptBridge", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "marcuswestin": "marcus.westin@gmail.com" 12 | }, 13 | "source": { 14 | "git": "https://github.com/marcuswestin/WebViewJavascriptBridge.git", 15 | "tag": "v6.0.2" 16 | }, 17 | "platforms": { 18 | "ios": "5.0", 19 | "osx": "" 20 | }, 21 | "requires_arc": true, 22 | "ios": { 23 | "source_files": "WebViewJavascriptBridge/*.{h,m}", 24 | "private_header_files": "WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h", 25 | "frameworks": [ 26 | "UIKit", 27 | "WebKit" 28 | ] 29 | }, 30 | "osx": { 31 | "source_files": "WebViewJavascriptBridge/*.{h,m}", 32 | "private_header_files": "WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h" 33 | }, 34 | "frameworks": "WebKit" 35 | } 36 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - WebViewJavascriptBridge (6.0.2) 3 | 4 | DEPENDENCIES: 5 | - WebViewJavascriptBridge (from `../..`) 6 | 7 | EXTERNAL SOURCES: 8 | WebViewJavascriptBridge: 9 | :path: ../.. 10 | 11 | SPEC CHECKSUMS: 12 | WebViewJavascriptBridge: 791ee0e26d1bf15efe5fb7fb9666a71a19b89d77 13 | 14 | PODFILE CHECKSUM: f657cfcc5a24b7c7f0c7781719b73d4a834bc276 15 | 16 | COCOAPODS: 1.1.1 17 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## WebViewJavascriptBridge 5 | 6 | Copyright (c) 2011-2015 Marcus Westin, Antoine Lagadec 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | Generated by CocoaPods - https://cocoapods.org 30 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2011-2015 Marcus Westin, Antoine Lagadec 18 | 19 | Permission is hereby granted, free of charge, to any person 20 | obtaining a copy of this software and associated documentation 21 | files (the "Software"), to deal in the Software without 22 | restriction, including without limitation the rights to use, 23 | copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | copies of the Software, and to permit persons to whom the 25 | Software is furnished to do so, subject to the following 26 | conditions: 27 | 28 | The above copyright notice and this permission notice shall be 29 | included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 33 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 35 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 36 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 37 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 38 | OTHER DEALINGS IN THE SOFTWARE. 39 | 40 | License 41 | MIT 42 | Title 43 | WebViewJavascriptBridge 44 | Type 45 | PSGroupSpecifier 46 | 47 | 48 | FooterText 49 | Generated by CocoaPods - https://cocoapods.org 50 | Title 51 | 52 | Type 53 | PSGroupSpecifier 54 | 55 | 56 | StringsTable 57 | Acknowledgements 58 | Title 59 | Acknowledgements 60 | 61 | 62 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ExampleSwiftApp_iOS : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ExampleSwiftApp_iOS 5 | @end 6 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | install_resource() 27 | { 28 | if [[ "$1" = /* ]] ; then 29 | RESOURCE_PATH="$1" 30 | else 31 | RESOURCE_PATH="${PODS_ROOT}/$1" 32 | fi 33 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 34 | cat << EOM 35 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 36 | EOM 37 | exit 1 38 | fi 39 | case $RESOURCE_PATH in 40 | *.storyboard) 41 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 42 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 43 | ;; 44 | *.xib) 45 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 46 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 47 | ;; 48 | *.framework) 49 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 50 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 51 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 52 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | ;; 54 | *.xcdatamodel) 55 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 56 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 57 | ;; 58 | *.xcdatamodeld) 59 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 60 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 61 | ;; 62 | *.xcmappingmodel) 63 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 64 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 65 | ;; 66 | *.xcassets) 67 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 68 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 69 | ;; 70 | *) 71 | echo "$RESOURCE_PATH" 72 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 73 | ;; 74 | esac 75 | } 76 | 77 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 78 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 79 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 80 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | fi 83 | rm -f "$RESOURCES_TO_COPY" 84 | 85 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 86 | then 87 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 88 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 89 | while read line; do 90 | if [[ $line != "${PODS_ROOT}*" ]]; then 91 | XCASSET_FILES+=("$line") 92 | fi 93 | done <<<"$OTHER_XCASSETS" 94 | 95 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | fi 97 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_ExampleSwiftApp_iOSVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_ExampleSwiftApp_iOSVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "WebViewJavascriptBridge" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_ExampleSwiftApp_iOS { 2 | umbrella header "Pods-ExampleSwiftApp-iOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOS/Pods-ExampleSwiftApp-iOS.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "WebViewJavascriptBridge" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## WebViewJavascriptBridge 5 | 6 | Copyright (c) 2011-2015 Marcus Westin, Antoine Lagadec 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | Generated by CocoaPods - https://cocoapods.org 30 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2011-2015 Marcus Westin, Antoine Lagadec 18 | 19 | Permission is hereby granted, free of charge, to any person 20 | obtaining a copy of this software and associated documentation 21 | files (the "Software"), to deal in the Software without 22 | restriction, including without limitation the rights to use, 23 | copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | copies of the Software, and to permit persons to whom the 25 | Software is furnished to do so, subject to the following 26 | conditions: 27 | 28 | The above copyright notice and this permission notice shall be 29 | included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 32 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 33 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 34 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 35 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 36 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 37 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 38 | OTHER DEALINGS IN THE SOFTWARE. 39 | 40 | License 41 | MIT 42 | Title 43 | WebViewJavascriptBridge 44 | Type 45 | PSGroupSpecifier 46 | 47 | 48 | FooterText 49 | Generated by CocoaPods - https://cocoapods.org 50 | Title 51 | 52 | Type 53 | PSGroupSpecifier 54 | 55 | 56 | StringsTable 57 | Acknowledgements 58 | Title 59 | Acknowledgements 60 | 61 | 62 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_ExampleSwiftApp_iOSTests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_ExampleSwiftApp_iOSTests 5 | @end 6 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | install_resource() 27 | { 28 | if [[ "$1" = /* ]] ; then 29 | RESOURCE_PATH="$1" 30 | else 31 | RESOURCE_PATH="${PODS_ROOT}/$1" 32 | fi 33 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 34 | cat << EOM 35 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 36 | EOM 37 | exit 1 38 | fi 39 | case $RESOURCE_PATH in 40 | *.storyboard) 41 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 42 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 43 | ;; 44 | *.xib) 45 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 46 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 47 | ;; 48 | *.framework) 49 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 50 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 51 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 52 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | ;; 54 | *.xcdatamodel) 55 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 56 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 57 | ;; 58 | *.xcdatamodeld) 59 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 60 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 61 | ;; 62 | *.xcmappingmodel) 63 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 64 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 65 | ;; 66 | *.xcassets) 67 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 68 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 69 | ;; 70 | *) 71 | echo "$RESOURCE_PATH" 72 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 73 | ;; 74 | esac 75 | } 76 | 77 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 78 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 79 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 80 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | fi 83 | rm -f "$RESOURCES_TO_COPY" 84 | 85 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 86 | then 87 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 88 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 89 | while read line; do 90 | if [[ $line != "${PODS_ROOT}*" ]]; then 91 | XCASSET_FILES+=("$line") 92 | fi 93 | done <<<"$OTHER_XCASSETS" 94 | 95 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | fi 97 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_ExampleSwiftApp_iOSTestsVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_ExampleSwiftApp_iOSTestsVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "WebViewJavascriptBridge" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_ExampleSwiftApp_iOSTests { 2 | umbrella header "Pods-ExampleSwiftApp-iOSTests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/Pods-ExampleSwiftApp-iOSTests/Pods-ExampleSwiftApp-iOSTests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge/WebViewJavascriptBridge.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "WebViewJavascriptBridge" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 6.0.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/WebViewJavascriptBridge-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_WebViewJavascriptBridge : NSObject 3 | @end 4 | @implementation PodsDummy_WebViewJavascriptBridge 5 | @end 6 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/WebViewJavascriptBridge-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/WebViewJavascriptBridge-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "WebViewJavascriptBridge.h" 6 | #import "WebViewJavascriptBridgeBase.h" 7 | #import "WKWebViewJavascriptBridge.h" 8 | 9 | FOUNDATION_EXPORT double WebViewJavascriptBridgeVersionNumber; 10 | FOUNDATION_EXPORT const unsigned char WebViewJavascriptBridgeVersionString[]; 11 | 12 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/WebViewJavascriptBridge.modulemap: -------------------------------------------------------------------------------- 1 | framework module WebViewJavascriptBridge { 2 | umbrella header "WebViewJavascriptBridge-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/Pods/Target Support Files/WebViewJavascriptBridge/WebViewJavascriptBridge.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/WebViewJavascriptBridge 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_LDFLAGS = -framework "UIKit" -framework "WebKit" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example Apps/ExampleSwiftApp-iOS/echo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

WebViewJavascriptBridgeTests - echo.html

5 | 33 | 34 | -------------------------------------------------------------------------------- /Example Apps/TestConsole.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 |

WebViewJavascriptBridge Demo Test console.log

12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2015 Marcus Westin, Antoine Lagadec 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | xcodebuild test -project Tests/WebViewJavascriptBridge.xcodeproj -scheme WebViewJavascriptBridge \ 3 | -destination 'platform=iOS Simulator,name=iPhone 8' 4 | xcodebuild test -workspace Example\ Apps/ExampleSwiftApp-iOS/ExampleSwiftApp-iOS.xcworkspace -scheme ExampleSwiftApp-iOS \ 5 | -destination 'platform=iOS Simulator,name=iPhone 8' 6 | 7 | test-many: 8 | xcodebuild test -project Tests/WebViewJavascriptBridge.xcodeproj -scheme WebViewJavascriptBridge \ 9 | -destination 'platform=iOS Simulator,name=iPhone 6' \ 10 | -destination 'platform=iOS Simulator,name=iPhone 7' \ 11 | -destination 'platform=iOS Simulator,name=iPhone 8' 12 | 13 | test-circle-ci: 14 | xcodebuild test -project Tests/WebViewJavascriptBridge.xcodeproj -scheme WebViewJavascriptBridge \ 15 | -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.3.1' \ 16 | -destination 'platform=iOS Simulator,name=iPhone X,OS=11.0.1' 17 | 18 | 19 | publish-pod: 20 | # pod trunk register narcvs@gmail.com 'Marcus Westin' --description='MBA/MBP-xyz' 21 | # First, bump podspec version, then commit & create tag: `git tag -a "v5.X.Y" -m "Tag v5.X.Y" && git push --tags` 22 | pod trunk push --verbose WebViewJavascriptBridge.podspec 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WebViewJavascriptBridge 2 | ======================= 3 | 4 | An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews. Also easy to get js console.log. 5 | 6 | More simple more light. Refactor WebViewJavascriptBridge with AOP 7 | ========================== 8 | 9 | How to use ? 10 | ========================== 11 | 12 | ### Installation with CocoaPods 13 | Add this to your [podfile](https://guides.cocoapods.org/using/getting-started.html) and run `pod install` to install: 14 | 15 | ```ruby 16 | pod 'SKJavaScriptBridge', '~> 1.0.3' 17 | ``` 18 | If you can't find the last version, maybe you need to update local pod repo. 19 | ```ruby 20 | pod repo update 21 | ``` 22 | 23 | ### Manual installation 24 | Drag the `WebViewJavascriptBridge` folder into your project. 25 | 26 | In the dialog that appears, uncheck "Copy items into destination group's folder" and select "Create groups for any folders". 27 | 28 | Usage 29 | ----- 30 | 1) Import the header file and declare an ivar property: 31 | 32 | ```objc 33 | #import "WebViewJavascriptBridge.h" 34 | ``` 35 | ```objc 36 | @property (nonatomic, strong) WKWebView *webView; 37 | @property (nonatomic, strong) WebViewJavascriptBridge* bridge; 38 | ``` 39 | 40 | ```objc 41 | self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; 42 | [self.view addSubview:self.webView]; 43 | if(!_bridge){ 44 | _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView 45 | showJSconsole:YES 46 | enableLogging:YES]; 47 | } 48 | ``` 49 | 50 | 2) Register a handler in ObjC, and call a JS handler: 51 | 52 | ```objc 53 | [_bridge registerHandler:@"ObjC Echo" handler:^(id data, WVJBResponseCallback responseCallback) { 54 | NSLog(@"ObjC Echo called with: %@", data); 55 | responseCallback(data); 56 | }]; 57 | [_bridge callHandler:@"JS Echo" data:nil responseCallback:^(id responseData) { 58 | NSLog(@"ObjC received response: %@", responseData); 59 | }]; 60 | ``` 61 | 3) Copy and paste `setupWebViewJavascriptBridge` into your JS: 62 | 63 | ```javascript 64 | function setupWebViewJavascriptBridge(callback) { 65 | return callback(WebViewJavascriptBridge); 66 | } 67 | ``` 68 | 5) Finally, call `setupWebViewJavascriptBridge` and then use the bridge to register handlers and call ObjC handlers: 69 | 70 | ```javascript 71 | setupWebViewJavascriptBridge(function(bridge) { 72 | 73 | /* Initialize your app here */ 74 | 75 | bridge.registerHandler('JS Echo', function(data, responseCallback) { 76 | console.log("JS Echo called with:", data) 77 | responseCallback(data) 78 | }) 79 | bridge.callHandler('ObjC Echo', {'key':'value'}, function responseCallback(responseData) { 80 | console.log("JS received response:", responseData) 81 | }) 82 | }) 83 | ``` 84 | 85 | -------------------------------------------------------------------------------- /Roadmap.md: -------------------------------------------------------------------------------- 1 | Roadmap 2 | ======= 3 | ###通过使用该库可以轻松实现JS与原生交互。 4 | 5 | Issues 6 | ------ 7 | 8 | - [X] `make test` fails becuase the command line invocation can't find WebKit framework. Fix. 9 | - [ ] Sometimes tests randomly fail! Race condition... 10 | - [X] Add WKWebView support to podspec file? (#149) 11 | - [ ] iOS8 WKWebView support? (#126) 12 | - [ ] WKWebView issue in OSX? (#84) 13 | - [ ] Release new version (#143, #155, #167) 14 | - [ ] Optional alert-unsafe message speedup (PR #133, I #132) 15 | - [ ] Swift and WKWebView (#153, #158) 16 | - [ ] Misc fixes 17 | - [ ] Crash on _deserializeMessageJSON (I #159) 18 | - [ ] Memory leak? (I #144) 19 | - [ ] Pictures/_dispatchMessage queue issue? (I #137) 20 | - [ ] Consider making webpage reloads easier (I #134) 21 | - [ ] Fix use in $(document).ready (I #131) 22 | - [ ] Error message on missing handler (I #120) 23 | - [ ] Pending bug repro/info 24 | - [ ] #123: unity3d and WebViewJavascriptBridge unrecognized selector sent to instance 25 | - [ ] #124: Getting an exception during _flushMessageQueue 26 | 27 | Misc 28 | ---- 29 | 30 | - [ ] Clean up webview delegate - can we get away without passing through one now? 31 | - [ ] Make bridge a subclass of UI/WKWebView 32 | - [ ] Scrap UIWebView? 33 | - [ ] Style consistency through all code 34 | - [ ] Test pod 35 | - [X] Fix OSX lint warnings (`pod spec lint`) 36 | - [X] I believe `receiveMessageQueue` in JS is no longer needed, since the JS explicitly tells ObjC when to start sending messages. Remove? 37 | 38 | v5.0.1 39 | ------ 40 | 41 | Pull requests: 42 | - [X] Dev env / docs 43 | - [X] Automated tests (PR #128, I #151) 44 | - [X] Travis? https://github.com/integrations/feature/code 45 | - [X] Embed js in objc source (PR #129) 46 | - [X] Also fixes PR #138, I #160, I #108 47 | - [X] Docs for podfile installation (PR #140) 48 | - [X] Improve API 49 | - [X] Remove default bridge handler - just do command/response. Remove bridge.init 50 | - [X] Features & fixes to consider 51 | - [X] Message response timeout (PR #106) 52 | - [X] Remove or fix numRequestsLoading (PR #146, PR #157) 53 | - [X] Net load fixes 54 | - [X] Fix `[webView stopLoading]` (PR #168, I #163) 55 | - [x] Detect offline failed requests (PR #170) 56 | - [X] Handle redirects (PR #172) 57 | - [X] Bridge never initiates without a didLoad (I #156) 58 | 59 | Future considerations 60 | --------------------- 61 | - [ ] Swift 62 | - [ ] Swift examples (I #173) 63 | - [ ] Javascript 64 | - [ ] Cookie set in client is not sent (I #171) 65 | - [ ] Form submission error (I #169) 66 | - [ ] React Native 67 | - [ ] Example app (I #162) 68 | - [ ] New features to consider 69 | - [ ] Multiple handlers: pubsub (I #119) 70 | - [ ] Remove handlers (I #118) 71 | - [ ] Other platforms to consider 72 | - [ ] Android - partly done by @fangj (#103) 73 | - [ ] Chrome - partly done by @fangj (#104) 74 | - [ ] Windows phone 75 | 76 | 77 | Common Messages 78 | --------------- 79 | 80 | #### Fixed in v5.x.y: 81 | 82 | Hi! 83 | 84 | I believe this may be fixed in v5.0.1. 85 | 86 | When you switch to the new version, please note that the API has changed. In particular, make sure that you use the javascript setup code, as it has changed: https://github.com/marcuswestin/WebViewJavascriptBridge#usage 87 | 88 | If you are still having trouble when using v5.0.x, feel free to reopen. 89 | 90 | Cheers! 91 | 92 | 93 | #### Need repro: 94 | 95 | Hi! 96 | 97 | Without a repro I won't be able to help you :( 98 | 99 | If you create a PR with a failing test then I will definitely give you a hand (see https://github.com/marcuswestin/WebViewJavascriptBridge/blob/master/Tests/WebViewJavascriptBridgeTests/BridgeTests.m and https://github.com/marcuswestin/WebViewJavascriptBridge/blob/master/Tests/WebViewJavascriptBridgeTests/echo.html). 100 | 101 | You could also create a PR with an example in `Example Apps` with the problem you're seeing in - that would definitely help me help you :) 102 | 103 | I'll close this in the meantime since there's nothing I can do. Feel free to reopen with a repro or more information. 104 | 105 | Cheers! 106 | -------------------------------------------------------------------------------- /Tests/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/housenkui/WebViewJavascriptBridge/63ef08930ffcf62c3854cc1dd2e8b9fec43202aa/Tests/Default-568h@2x.png -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridge.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2C35E9761C5A7F8E0093FB29 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2C35E9751C5A7F8E0093FB29 /* Default-568h@2x.png */; }; 11 | 2C3E7C631C5A928700A1E322 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C5C1C5A928700A1E322 /* WebViewJavascriptBridge.m */; }; 12 | 2C3E7C641C5A928700A1E322 /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C5E1C5A928700A1E322 /* WebViewJavascriptBridge_JS.m */; }; 13 | 2C3E7C651C5A928700A1E322 /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C601C5A928700A1E322 /* WebViewJavascriptBridgeBase.m */; }; 14 | 2C3E7C661C5A928700A1E322 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C3E7C621C5A928700A1E322 /* WKWebViewJavascriptBridge.m */; }; 15 | 2C52B1E21E11858800517DAF /* BridgeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C52B1E11E11858800517DAF /* BridgeTests.swift */; }; 16 | 2C864FFD1C60FC8A00954B70 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C864FFC1C60FC8A00954B70 /* WebKit.framework */; }; 17 | 3D99867E1AE2A3B2001DDA2C /* echo.html in Resources */ = {isa = PBXBuildFile; fileRef = 3D99867D1AE2A3B2001DDA2C /* echo.html */; }; 18 | 3D9E5F2F1AE288E5009D1C36 /* BridgeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D9E5F2E1AE288E5009D1C36 /* BridgeTests.m */; }; 19 | 3DCCF7DB1AE28C2900CE7C51 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DCCF7DA1AE28C2900CE7C51 /* main.m */; }; 20 | 3DCCF7DE1AE28C2900CE7C51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DCCF7DD1AE28C2900CE7C51 /* AppDelegate.m */; }; 21 | 3DCCF8021AE2911100CE7C51 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DCCF8011AE2911100CE7C51 /* UIKit.framework */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 3DCCF7FC1AE28C3B00CE7C51 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 3D0FE4621AE2886400BB4104 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 3DCCF7D51AE28C2900CE7C51; 30 | remoteInfo = WebViewJavascriptBridgeTestHost; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 2C35E9751C5A7F8E0093FB29 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 36 | 2C3E7C5B1C5A928700A1E322 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 37 | 2C3E7C5C1C5A928700A1E322 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 38 | 2C3E7C5D1C5A928700A1E322 /* WebViewJavascriptBridge_JS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_JS.h; sourceTree = ""; }; 39 | 2C3E7C5E1C5A928700A1E322 /* WebViewJavascriptBridge_JS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_JS.m; sourceTree = ""; }; 40 | 2C3E7C5F1C5A928700A1E322 /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; 41 | 2C3E7C601C5A928700A1E322 /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; 42 | 2C3E7C611C5A928700A1E322 /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; 43 | 2C3E7C621C5A928700A1E322 /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; 44 | 2C52B1E01E11858800517DAF /* WebViewJavascriptBridgeTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WebViewJavascriptBridgeTests-Bridging-Header.h"; sourceTree = ""; }; 45 | 2C52B1E11E11858800517DAF /* BridgeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgeTests.swift; sourceTree = ""; }; 46 | 2C864FFC1C60FC8A00954B70 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 47 | 3D0FE4751AE2886500BB4104 /* WebViewJavascriptBridgeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebViewJavascriptBridgeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 3D0FE47B1AE2886500BB4104 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 3D99867D1AE2A3B2001DDA2C /* echo.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = echo.html; path = WebViewJavascriptBridgeTests/echo.html; sourceTree = SOURCE_ROOT; }; 50 | 3D9E5F2E1AE288E5009D1C36 /* BridgeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BridgeTests.m; sourceTree = ""; }; 51 | 3DCCF7D61AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebViewJavascriptBridgeTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 3DCCF7D91AE28C2900CE7C51 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 3DCCF7DA1AE28C2900CE7C51 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | 3DCCF7DC1AE28C2900CE7C51 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 55 | 3DCCF7DD1AE28C2900CE7C51 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 56 | 3DCCF8011AE2911100CE7C51 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 3D0FE4721AE2886500BB4104 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | 2C864FFD1C60FC8A00954B70 /* WebKit.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | 3DCCF7D31AE28C2900CE7C51 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 3DCCF8021AE2911100CE7C51 /* UIKit.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 2C3E7C5A1C5A928700A1E322 /* WebViewJavascriptBridge */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 2C3E7C5B1C5A928700A1E322 /* WebViewJavascriptBridge.h */, 83 | 2C3E7C5C1C5A928700A1E322 /* WebViewJavascriptBridge.m */, 84 | 2C3E7C5D1C5A928700A1E322 /* WebViewJavascriptBridge_JS.h */, 85 | 2C3E7C5E1C5A928700A1E322 /* WebViewJavascriptBridge_JS.m */, 86 | 2C3E7C5F1C5A928700A1E322 /* WebViewJavascriptBridgeBase.h */, 87 | 2C3E7C601C5A928700A1E322 /* WebViewJavascriptBridgeBase.m */, 88 | 2C3E7C611C5A928700A1E322 /* WKWebViewJavascriptBridge.h */, 89 | 2C3E7C621C5A928700A1E322 /* WKWebViewJavascriptBridge.m */, 90 | ); 91 | name = WebViewJavascriptBridge; 92 | path = ../WebViewJavascriptBridge; 93 | sourceTree = ""; 94 | }; 95 | 3D0FE4611AE2886400BB4104 = { 96 | isa = PBXGroup; 97 | children = ( 98 | 2C864FFC1C60FC8A00954B70 /* WebKit.framework */, 99 | 2C35E9751C5A7F8E0093FB29 /* Default-568h@2x.png */, 100 | 2C3E7C5A1C5A928700A1E322 /* WebViewJavascriptBridge */, 101 | 3D0FE4791AE2886500BB4104 /* WebViewJavascriptBridgeTests */, 102 | 3DCCF7D71AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost */, 103 | 3D0FE46B1AE2886400BB4104 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 3D0FE46B1AE2886400BB4104 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 3D0FE4751AE2886500BB4104 /* WebViewJavascriptBridgeTests.xctest */, 111 | 3DCCF7D61AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost.app */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 3D0FE4791AE2886500BB4104 /* WebViewJavascriptBridgeTests */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 3D0FE47A1AE2886500BB4104 /* Supporting Files */, 120 | 3D9E5F2E1AE288E5009D1C36 /* BridgeTests.m */, 121 | 2C52B1E11E11858800517DAF /* BridgeTests.swift */, 122 | 2C52B1E01E11858800517DAF /* WebViewJavascriptBridgeTests-Bridging-Header.h */, 123 | ); 124 | path = WebViewJavascriptBridgeTests; 125 | sourceTree = ""; 126 | }; 127 | 3D0FE47A1AE2886500BB4104 /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 3D0FE47B1AE2886500BB4104 /* Info.plist */, 131 | ); 132 | name = "Supporting Files"; 133 | sourceTree = ""; 134 | }; 135 | 3DCCF7D71AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 3DCCF7DC1AE28C2900CE7C51 /* AppDelegate.h */, 139 | 3DCCF7DD1AE28C2900CE7C51 /* AppDelegate.m */, 140 | 3DCCF8031AE2911700CE7C51 /* Frameworks */, 141 | 3DCCF7D81AE28C2900CE7C51 /* Supporting Files */, 142 | ); 143 | path = WebViewJavascriptBridgeTestHost; 144 | sourceTree = ""; 145 | }; 146 | 3DCCF7D81AE28C2900CE7C51 /* Supporting Files */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 3D99867D1AE2A3B2001DDA2C /* echo.html */, 150 | 3DCCF7D91AE28C2900CE7C51 /* Info.plist */, 151 | 3DCCF7DA1AE28C2900CE7C51 /* main.m */, 152 | ); 153 | name = "Supporting Files"; 154 | sourceTree = ""; 155 | }; 156 | 3DCCF8031AE2911700CE7C51 /* Frameworks */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 3DCCF8011AE2911100CE7C51 /* UIKit.framework */, 160 | ); 161 | name = Frameworks; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 3D0FE4741AE2886500BB4104 /* WebViewJavascriptBridgeTests */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 3D0FE4811AE2886500BB4104 /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridgeTests" */; 170 | buildPhases = ( 171 | 3D0FE4711AE2886500BB4104 /* Sources */, 172 | 3D0FE4721AE2886500BB4104 /* Frameworks */, 173 | 3D0FE4731AE2886500BB4104 /* Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | 3DCCF7FD1AE28C3B00CE7C51 /* PBXTargetDependency */, 179 | ); 180 | name = WebViewJavascriptBridgeTests; 181 | productName = WebViewJavascriptBridgeTests; 182 | productReference = 3D0FE4751AE2886500BB4104 /* WebViewJavascriptBridgeTests.xctest */; 183 | productType = "com.apple.product-type.bundle.unit-test"; 184 | }; 185 | 3DCCF7D51AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 3DCCF7FA1AE28C2900CE7C51 /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridgeTestHost" */; 188 | buildPhases = ( 189 | 3DCCF7D21AE28C2900CE7C51 /* Sources */, 190 | 3DCCF7D31AE28C2900CE7C51 /* Frameworks */, 191 | 3DCCF7D41AE28C2900CE7C51 /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | ); 197 | name = WebViewJavascriptBridgeTestHost; 198 | productName = WebViewJavascriptBridgeTestHost; 199 | productReference = 3DCCF7D61AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost.app */; 200 | productType = "com.apple.product-type.application"; 201 | }; 202 | /* End PBXNativeTarget section */ 203 | 204 | /* Begin PBXProject section */ 205 | 3D0FE4621AE2886400BB4104 /* Project object */ = { 206 | isa = PBXProject; 207 | attributes = { 208 | LastUpgradeCheck = 0900; 209 | ORGANIZATIONNAME = marcuswestin; 210 | TargetAttributes = { 211 | 3D0FE4741AE2886500BB4104 = { 212 | CreatedOnToolsVersion = 6.3; 213 | LastSwiftMigration = 0900; 214 | TestTargetID = 3DCCF7D51AE28C2900CE7C51; 215 | }; 216 | 3DCCF7D51AE28C2900CE7C51 = { 217 | CreatedOnToolsVersion = 6.3; 218 | }; 219 | }; 220 | }; 221 | buildConfigurationList = 3D0FE4651AE2886400BB4104 /* Build configuration list for PBXProject "WebViewJavascriptBridge" */; 222 | compatibilityVersion = "Xcode 3.2"; 223 | developmentRegion = English; 224 | hasScannedForEncodings = 0; 225 | knownRegions = ( 226 | en, 227 | Base, 228 | ); 229 | mainGroup = 3D0FE4611AE2886400BB4104; 230 | productRefGroup = 3D0FE46B1AE2886400BB4104 /* Products */; 231 | projectDirPath = ""; 232 | projectRoot = ""; 233 | targets = ( 234 | 3D0FE4741AE2886500BB4104 /* WebViewJavascriptBridgeTests */, 235 | 3DCCF7D51AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost */, 236 | ); 237 | }; 238 | /* End PBXProject section */ 239 | 240 | /* Begin PBXResourcesBuildPhase section */ 241 | 3D0FE4731AE2886500BB4104 /* Resources */ = { 242 | isa = PBXResourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | 3DCCF7D41AE28C2900CE7C51 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | 3D99867E1AE2A3B2001DDA2C /* echo.html in Resources */, 253 | 2C35E9761C5A7F8E0093FB29 /* Default-568h@2x.png in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | 3D0FE4711AE2886500BB4104 /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 2C3E7C651C5A928700A1E322 /* WebViewJavascriptBridgeBase.m in Sources */, 265 | 2C3E7C661C5A928700A1E322 /* WKWebViewJavascriptBridge.m in Sources */, 266 | 3D9E5F2F1AE288E5009D1C36 /* BridgeTests.m in Sources */, 267 | 2C3E7C631C5A928700A1E322 /* WebViewJavascriptBridge.m in Sources */, 268 | 2C52B1E21E11858800517DAF /* BridgeTests.swift in Sources */, 269 | 2C3E7C641C5A928700A1E322 /* WebViewJavascriptBridge_JS.m in Sources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | 3DCCF7D21AE28C2900CE7C51 /* Sources */ = { 274 | isa = PBXSourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | 3DCCF7DE1AE28C2900CE7C51 /* AppDelegate.m in Sources */, 278 | 3DCCF7DB1AE28C2900CE7C51 /* main.m in Sources */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | /* End PBXSourcesBuildPhase section */ 283 | 284 | /* Begin PBXTargetDependency section */ 285 | 3DCCF7FD1AE28C3B00CE7C51 /* PBXTargetDependency */ = { 286 | isa = PBXTargetDependency; 287 | target = 3DCCF7D51AE28C2900CE7C51 /* WebViewJavascriptBridgeTestHost */; 288 | targetProxy = 3DCCF7FC1AE28C3B00CE7C51 /* PBXContainerItemProxy */; 289 | }; 290 | /* End PBXTargetDependency section */ 291 | 292 | /* Begin XCBuildConfiguration section */ 293 | 3D0FE47C1AE2886500BB4104 /* Debug */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | ALWAYS_SEARCH_USER_PATHS = NO; 297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 298 | CLANG_CXX_LIBRARY = "libc++"; 299 | CLANG_ENABLE_MODULES = YES; 300 | CLANG_ENABLE_OBJC_ARC = YES; 301 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 302 | CLANG_WARN_BOOL_CONVERSION = YES; 303 | CLANG_WARN_COMMA = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INFINITE_RECURSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 311 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 312 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 313 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 314 | CLANG_WARN_STRICT_PROTOTYPES = YES; 315 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 316 | CLANG_WARN_UNREACHABLE_CODE = YES; 317 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 318 | COPY_PHASE_STRIP = NO; 319 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 320 | ENABLE_STRICT_OBJC_MSGSEND = YES; 321 | ENABLE_TESTABILITY = YES; 322 | GCC_C_LANGUAGE_STANDARD = gnu99; 323 | GCC_DYNAMIC_NO_PIC = NO; 324 | GCC_NO_COMMON_BLOCKS = YES; 325 | GCC_OPTIMIZATION_LEVEL = 0; 326 | GCC_PREPROCESSOR_DEFINITIONS = ( 327 | "DEBUG=1", 328 | "$(inherited)", 329 | ); 330 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 338 | MTL_ENABLE_DEBUG_INFO = YES; 339 | ONLY_ACTIVE_ARCH = YES; 340 | SDKROOT = iphoneos; 341 | }; 342 | name = Debug; 343 | }; 344 | 3D0FE47D1AE2886500BB4104 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ALWAYS_SEARCH_USER_PATHS = NO; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 353 | CLANG_WARN_BOOL_CONVERSION = YES; 354 | CLANG_WARN_COMMA = YES; 355 | CLANG_WARN_CONSTANT_CONVERSION = YES; 356 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 357 | CLANG_WARN_EMPTY_BODY = YES; 358 | CLANG_WARN_ENUM_CONVERSION = YES; 359 | CLANG_WARN_INFINITE_RECURSION = YES; 360 | CLANG_WARN_INT_CONVERSION = YES; 361 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 362 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 363 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 364 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 365 | CLANG_WARN_STRICT_PROTOTYPES = YES; 366 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 367 | CLANG_WARN_UNREACHABLE_CODE = YES; 368 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 369 | COPY_PHASE_STRIP = NO; 370 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 371 | ENABLE_NS_ASSERTIONS = NO; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | GCC_C_LANGUAGE_STANDARD = gnu99; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 376 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 377 | GCC_WARN_UNDECLARED_SELECTOR = YES; 378 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 379 | GCC_WARN_UNUSED_FUNCTION = YES; 380 | GCC_WARN_UNUSED_VARIABLE = YES; 381 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 382 | MTL_ENABLE_DEBUG_INFO = NO; 383 | SDKROOT = iphoneos; 384 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 385 | VALIDATE_PRODUCT = YES; 386 | }; 387 | name = Release; 388 | }; 389 | 3D0FE4821AE2886500BB4104 /* Debug */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | CLANG_ENABLE_MODULES = YES; 393 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 394 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 395 | GCC_PREPROCESSOR_DEFINITIONS = ( 396 | "DEBUG=1", 397 | "$(inherited)", 398 | ); 399 | INFOPLIST_FILE = WebViewJavascriptBridgeTests/Info.plist; 400 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 401 | PRODUCT_BUNDLE_IDENTIFIER = "in.marcuswestin.WebViewJavascriptBridge.$(PRODUCT_NAME:rfc1034identifier)"; 402 | PRODUCT_NAME = "$(TARGET_NAME)"; 403 | SWIFT_OBJC_BRIDGING_HEADER = "WebViewJavascriptBridgeTests/WebViewJavascriptBridgeTests-Bridging-Header.h"; 404 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 405 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 406 | SWIFT_VERSION = 4.0; 407 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WebViewJavascriptBridgeTestHost.app/WebViewJavascriptBridgeTestHost"; 408 | }; 409 | name = Debug; 410 | }; 411 | 3D0FE4831AE2886500BB4104 /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | CLANG_ENABLE_MODULES = YES; 415 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 416 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 417 | INFOPLIST_FILE = WebViewJavascriptBridgeTests/Info.plist; 418 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 419 | PRODUCT_BUNDLE_IDENTIFIER = "in.marcuswestin.WebViewJavascriptBridge.$(PRODUCT_NAME:rfc1034identifier)"; 420 | PRODUCT_NAME = "$(TARGET_NAME)"; 421 | SWIFT_OBJC_BRIDGING_HEADER = "WebViewJavascriptBridgeTests/WebViewJavascriptBridgeTests-Bridging-Header.h"; 422 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 423 | SWIFT_VERSION = 4.0; 424 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WebViewJavascriptBridgeTestHost.app/WebViewJavascriptBridgeTestHost"; 425 | }; 426 | name = Release; 427 | }; 428 | 3DCCF7F61AE28C2900CE7C51 /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 432 | GCC_PREPROCESSOR_DEFINITIONS = ( 433 | "DEBUG=1", 434 | "$(inherited)", 435 | ); 436 | INFOPLIST_FILE = WebViewJavascriptBridgeTestHost/Info.plist; 437 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 439 | PRODUCT_BUNDLE_IDENTIFIER = "in.marcuswestin.$(PRODUCT_NAME:rfc1034identifier)"; 440 | PRODUCT_NAME = "$(TARGET_NAME)"; 441 | }; 442 | name = Debug; 443 | }; 444 | 3DCCF7F71AE28C2900CE7C51 /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 448 | INFOPLIST_FILE = WebViewJavascriptBridgeTestHost/Info.plist; 449 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 451 | PRODUCT_BUNDLE_IDENTIFIER = "in.marcuswestin.$(PRODUCT_NAME:rfc1034identifier)"; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | }; 454 | name = Release; 455 | }; 456 | /* End XCBuildConfiguration section */ 457 | 458 | /* Begin XCConfigurationList section */ 459 | 3D0FE4651AE2886400BB4104 /* Build configuration list for PBXProject "WebViewJavascriptBridge" */ = { 460 | isa = XCConfigurationList; 461 | buildConfigurations = ( 462 | 3D0FE47C1AE2886500BB4104 /* Debug */, 463 | 3D0FE47D1AE2886500BB4104 /* Release */, 464 | ); 465 | defaultConfigurationIsVisible = 0; 466 | defaultConfigurationName = Release; 467 | }; 468 | 3D0FE4811AE2886500BB4104 /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridgeTests" */ = { 469 | isa = XCConfigurationList; 470 | buildConfigurations = ( 471 | 3D0FE4821AE2886500BB4104 /* Debug */, 472 | 3D0FE4831AE2886500BB4104 /* Release */, 473 | ); 474 | defaultConfigurationIsVisible = 0; 475 | defaultConfigurationName = Release; 476 | }; 477 | 3DCCF7FA1AE28C2900CE7C51 /* Build configuration list for PBXNativeTarget "WebViewJavascriptBridgeTestHost" */ = { 478 | isa = XCConfigurationList; 479 | buildConfigurations = ( 480 | 3DCCF7F61AE28C2900CE7C51 /* Debug */, 481 | 3DCCF7F71AE28C2900CE7C51 /* Release */, 482 | ); 483 | defaultConfigurationIsVisible = 0; 484 | defaultConfigurationName = Release; 485 | }; 486 | /* End XCConfigurationList section */ 487 | }; 488 | rootObject = 3D0FE4621AE2886400BB4104 /* Project object */; 489 | } 490 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridge.xcodeproj/xcshareddata/xcschemes/WebViewJavascriptBridge.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 54 | 55 | 56 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 80 | 81 | 87 | 88 | 89 | 90 | 91 | 92 | 98 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTestHost/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WebViewJavascriptBridgeTestHost 4 | // 5 | // Created by Pieter De Baets on 18/04/2015. 6 | // Copyright (c) 2015 marcuswestin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTestHost/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WebViewJavascriptBridgeTestHost 4 | // 5 | // Created by Pieter De Baets on 18/04/2015. 6 | // Copyright (c) 2015 marcuswestin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 14 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 15 | self.window.rootViewController = [UIViewController new]; 16 | [self.window makeKeyAndVisible]; 17 | 18 | return YES; 19 | } 20 | 21 | - (void)applicationWillResignActive:(UIApplication *)application { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | - (void)applicationDidEnterBackground:(UIApplication *)application { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application { 32 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | - (void)applicationDidBecomeActive:(UIApplication *)application { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | - (void)applicationWillTerminate:(UIApplication *)application { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTestHost/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTestHost/WebViewJavascriptBridgeTestHost-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate-Bridging-Header.h 3 | // WebViewJavascriptBridge 4 | // 5 | // Created by John Marcus Westin on 12/27/16. 6 | // Copyright © 2016 marcuswestin. All rights reserved. 7 | // 8 | 9 | #ifndef AppDelegate_Bridging_Header_h 10 | #define AppDelegate_Bridging_Header_h 11 | 12 | 13 | #endif /* AppDelegate_Bridging_Header_h */ 14 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTestHost/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WebViewJavascriptBridgeTestHost 4 | // 5 | // Created by Pieter De Baets on 18/04/2015. 6 | // Copyright (c) 2015 marcuswestin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTests/BridgeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BridgeTests.m 3 | // WKWebViewJavascriptBridge 4 | // 5 | // Created by Pieter De Baets on 18/04/2015. 6 | // Copyright (c) 2015 marcuswestin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "WebViewJavascriptBridge.h" 12 | #import "AppDelegate.h" 13 | 14 | static NSString *const echoHandler = @"echoHandler"; 15 | 16 | @interface BridgeTests : XCTestCase 17 | @end 18 | @interface TestWebPageLoadDelegate : NSObject 19 | @property XCTestExpectation* expectation; 20 | @end 21 | 22 | @implementation BridgeTests { 23 | UIWebView *_uiWebView; 24 | WKWebView *_wkWebView; 25 | NSMutableArray* _retains; 26 | } 27 | 28 | - (void)setUp { 29 | [super setUp]; 30 | 31 | UIViewController *rootVC = [[(AppDelegate *)[[UIApplication sharedApplication] delegate] window] rootViewController]; 32 | CGRect frame = rootVC.view.bounds; 33 | frame.size.height /= 2; 34 | _uiWebView = [[UIWebView alloc] initWithFrame:frame]; 35 | _uiWebView.backgroundColor = [UIColor blueColor]; 36 | [rootVC.view addSubview:_uiWebView]; 37 | frame.origin.y += frame.size.height; 38 | _wkWebView = [[WKWebView alloc] initWithFrame:frame]; 39 | _wkWebView.backgroundColor = [UIColor redColor]; 40 | [rootVC.view addSubview:_wkWebView]; 41 | 42 | _retains = [NSMutableArray array]; 43 | } 44 | 45 | - (void)tearDown { 46 | [super tearDown]; 47 | [_uiWebView removeFromSuperview]; 48 | [_wkWebView removeFromSuperview]; 49 | } 50 | 51 | - (WebViewJavascriptBridge*)bridgeForWebView:(id)webView { 52 | WebViewJavascriptBridge* bridge = [WebViewJavascriptBridge bridgeForWebView:webView]; 53 | [_retains addObject:bridge]; 54 | return bridge; 55 | } 56 | 57 | static void loadEchoSample(id webView) { 58 | NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"echo" withExtension:@"html"]]; 59 | [(UIWebView*)webView loadRequest:request]; 60 | } 61 | 62 | const NSTimeInterval timeoutSec = 5; 63 | 64 | - (void)testEchoHandler { 65 | [self classSpecificTestEchoHandler:_uiWebView]; 66 | [self classSpecificTestEchoHandler:_wkWebView]; 67 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 68 | } 69 | - (void)classSpecificTestEchoHandler:(id)webView { 70 | WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView]; 71 | 72 | XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"]; 73 | [bridge callHandler:echoHandler data:@"testEchoHandler" responseCallback:^(id responseData) { 74 | XCTAssertEqualObjects(responseData, @"testEchoHandler"); 75 | [callbackInvocked fulfill]; 76 | }]; 77 | 78 | loadEchoSample(webView); 79 | } 80 | 81 | - (void)testEchoHandlerAfterSetup { 82 | [self classSpecificTestEchoHandlerAfterSetup:_uiWebView]; 83 | [self classSpecificTestEchoHandlerAfterSetup:_wkWebView]; 84 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 85 | } 86 | - (void)classSpecificTestEchoHandlerAfterSetup:(id)webView { 87 | WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView]; 88 | 89 | XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"]; 90 | loadEchoSample(webView); 91 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 150 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ 92 | [bridge callHandler:echoHandler data:@"testEchoHandler" responseCallback:^(id responseData) { 93 | XCTAssertEqualObjects(responseData, @"testEchoHandler"); 94 | [callbackInvocked fulfill]; 95 | }]; 96 | }); 97 | } 98 | 99 | - (void)testObjectEncoding { 100 | [self classSpecificTestObjectEncoding:_uiWebView]; 101 | [self classSpecificTestObjectEncoding:_wkWebView]; 102 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 103 | } 104 | - (void)classSpecificTestObjectEncoding:(id)webView { 105 | WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView]; 106 | 107 | void (^echoObject)(id) = ^void(id object) { 108 | XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"]; 109 | [bridge callHandler:echoHandler data:object responseCallback:^(id responseData) { 110 | XCTAssertEqualObjects(responseData, object); 111 | [callbackInvocked fulfill]; 112 | }]; 113 | }; 114 | 115 | echoObject(@"A string sent over the wire"); 116 | echoObject(@"A string with '\"'/\\"); 117 | echoObject(@[ @1, @2, @3 ]); 118 | echoObject(@{ @"a" : @1, @"b" : @2 }); 119 | 120 | loadEchoSample(webView); 121 | } 122 | 123 | - (void)testJavascriptReceiveResponse { 124 | [self classSpecificTestJavascriptReceiveResponse:_uiWebView]; 125 | [self classSpecificTestJavascriptReceiveResponse:_wkWebView]; 126 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 127 | } 128 | - (void)classSpecificTestJavascriptReceiveResponse:(id)webView { 129 | WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView]; 130 | loadEchoSample(webView); 131 | XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"]; 132 | [bridge registerHandler:@"objcEchoToJs" handler:^(id data, WVJBResponseCallback responseCallback) { 133 | responseCallback(data); 134 | }]; 135 | [bridge callHandler:@"jsRcvResponseTest" data:nil responseCallback:^(id responseData) { 136 | XCTAssertEqualObjects(responseData, @"Response from JS"); 137 | [callbackInvocked fulfill]; 138 | }]; 139 | } 140 | 141 | - (void)testJavascriptReceiveResponseWithoutSafetyTimeout { 142 | [self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:_uiWebView]; 143 | [self classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:_wkWebView]; 144 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 145 | } 146 | - (void)classSpecificTestJavascriptReceiveResponseWithoutSafetyTimeout:(id)webView { 147 | WebViewJavascriptBridge *bridge = [self bridgeForWebView:webView]; 148 | [bridge disableJavscriptAlertBoxSafetyTimeout]; 149 | loadEchoSample(webView); 150 | XCTestExpectation *callbackInvocked = [self expectationWithDescription:@"Callback invoked"]; 151 | [bridge registerHandler:@"objcEchoToJs" handler:^(id data, WVJBResponseCallback responseCallback) { 152 | responseCallback(data); 153 | }]; 154 | [bridge callHandler:@"jsRcvResponseTest" data:nil responseCallback:^(id responseData) { 155 | XCTAssertEqualObjects(responseData, @"Response from JS"); 156 | [callbackInvocked fulfill]; 157 | }]; 158 | } 159 | 160 | - (void)testWebpageLoad { 161 | [self classSpecificTestWebpageLoad:_uiWebView]; 162 | [self classSpecificTestWebpageLoad:_wkWebView]; 163 | [self waitForExpectationsWithTimeout:timeoutSec handler:NULL]; 164 | } 165 | - (void)classSpecificTestWebpageLoad:(id)webView { 166 | WebViewJavascriptBridge* bridge = [self bridgeForWebView:webView]; 167 | TestWebPageLoadDelegate* delegate = [TestWebPageLoadDelegate new]; 168 | delegate.expectation = [self expectationWithDescription:@"Webpage loaded"]; 169 | [_retains addObject:delegate]; 170 | [bridge setWebViewDelegate:delegate]; 171 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com"]]; 172 | [(UIWebView*)webView loadRequest:request]; 173 | } 174 | @end 175 | 176 | @implementation TestWebPageLoadDelegate 177 | - (void)webViewDidFinishLoad:(UIWebView *)webView { 178 | [self.expectation fulfill]; 179 | } 180 | - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { 181 | [self.expectation fulfill]; 182 | } 183 | @end 184 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTests/BridgeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BridgeTests.swift 3 | // WebViewJavascriptBridge 4 | // 5 | // Created by John Marcus Westin on 12/26/16. 6 | // Copyright © 2016 marcuswestin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class BridgeTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testExample() { 24 | // This is an example of a functional test case. 25 | // Use XCTAssert and related functions to verify your tests produce the correct results. 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measure { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTests/WebViewJavascriptBridgeTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /Tests/WebViewJavascriptBridgeTests/echo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

WebViewJavascriptBridgeTests - echo.html

5 | 32 | 33 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'WebViewJavascriptBridge' 3 | s.version = '6.0.3' 4 | s.summary = 'An iOS & OSX bridge for sending messages between Obj-C/Swift and JavaScript in WKWebViews, UIWebViews & WebViews.' 5 | s.homepage = 'https://github.com/marcuswestin/WebViewJavascriptBridge' 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { 'marcuswestin' => 'marcus.westin@gmail.com' } 8 | s.source = { :git => 'https://github.com/marcuswestin/WebViewJavascriptBridge.git', :tag => 'v'+s.version.to_s } 9 | s.platforms = { :ios => "5.0", :osx => "" } 10 | s.requires_arc = true 11 | 12 | s.ios.source_files = 'WebViewJavascriptBridge/*.{h,m}' 13 | s.ios.private_header_files = 'WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h' 14 | s.osx.source_files = 'WebViewJavascriptBridge/*.{h,m}' 15 | s.osx.private_header_files = 'WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h' 16 | 17 | s.frameworks = 'WebKit' 18 | s.ios.frameworks = 'UIKit', 'WebKit' 19 | end 20 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptBridge.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WebViewJavascriptBridgeBase.h" 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface WebViewJavascriptBridge : NSObject 15 | 16 | + (instancetype)bridgeForWebView:(WKWebView*)webView 17 | showJSconsole:(BOOL)show 18 | enableLogging:(BOOL)enable; 19 | - (void)registerHandler:(NSString*)handlerName handler:(nullable WVJBHandler)handler; 20 | - (void)removeHandler:( NSString* )handlerName; 21 | - (void)callHandler:(NSString*)handlerName; 22 | - (void)callHandler:(NSString*)handlerName data:(nullable id)data; 23 | - (void)callHandler:(NSString*)handlerName data:(nullable id)data responseCallback:(nullable WVJBResponseCallback)responseCallback; 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptBridge.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptBridge.h" 10 | #import "WebViewJavascriptLeakAvoider.h" 11 | #define kBridgePrefix @"__bridge__" 12 | 13 | @implementation WebViewJavascriptBridge { 14 | WKWebView* _webView; 15 | long _uniqueId; 16 | WebViewJavascriptBridgeBase *_base; 17 | BOOL _showJSconsole; 18 | BOOL _enableLogging; 19 | } 20 | 21 | + (instancetype)bridgeForWebView:(WKWebView*)webView 22 | showJSconsole:(BOOL)show 23 | enableLogging:(BOOL)enable { 24 | WebViewJavascriptBridge* bridge = [[self alloc] init]; 25 | [bridge _setupInstance:webView showJSconsole:show enableLogging:enable]; 26 | return bridge; 27 | } 28 | 29 | - (void)callHandler:(NSString *)handlerName { 30 | [self callHandler:handlerName data:nil responseCallback:nil]; 31 | } 32 | 33 | - (void)callHandler:(NSString *)handlerName data:(id)data { 34 | [self callHandler:handlerName data:data responseCallback:nil]; 35 | } 36 | 37 | - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 38 | [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; 39 | } 40 | 41 | - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { 42 | _base.messageHandlers[handlerName] = [handler copy]; 43 | } 44 | 45 | - (void)removeHandler:(NSString *)handlerName { 46 | [_base.messageHandlers removeObjectForKey:handlerName]; 47 | } 48 | 49 | 50 | - (void)_setupInstance:(WKWebView*)webView showJSconsole:(BOOL)show enableLogging:(BOOL)enable{ 51 | _webView = webView; 52 | _base = [[WebViewJavascriptBridgeBase alloc] init]; 53 | _base.delegate = self; 54 | _showJSconsole = show; 55 | _enableLogging = enable; 56 | 57 | [self addScriptMessageHandler]; 58 | [self _injectJavascriptFile]; 59 | } 60 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { 61 | NSString * body = (NSString * )message.body; 62 | if ([self _filterMessage:body]) { 63 | NSMutableString *mstr = [NSMutableString stringWithString:body]; 64 | [mstr replaceOccurrencesOfString:kBridgePrefix withString:@"" options:0 range:NSMakeRange(0, 10)]; 65 | [_base flushMessageQueue:mstr]; 66 | } 67 | } 68 | - (void)_injectJavascriptFile { 69 | NSString *bridge_js = WebViewJavascriptBridge_js(); 70 | //injected the method when H5 starts to create the DOM tree 71 | WKUserScript * bridge_userScript = [[WKUserScript alloc]initWithSource:bridge_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; 72 | [_webView.configuration.userContentController addUserScript:bridge_userScript]; 73 | if (_showJSconsole) { 74 | NSString *console_log_js = WebViewJavascriptBridge_console_log_js(); 75 | WKUserScript * console_log_userScript = [[WKUserScript alloc]initWithSource:console_log_js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; 76 | [_webView.configuration.userContentController addUserScript:console_log_userScript]; 77 | } 78 | } 79 | - (void) addScriptMessageHandler { 80 | [_webView.configuration.userContentController addScriptMessageHandler:[[WebViewJavascriptLeakAvoider alloc]initWithDelegate:self] name:@"pipe"]; 81 | } 82 | 83 | - (void)removeScriptMessageHandler { 84 | [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"pipe"]; 85 | } 86 | 87 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand { 88 | [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; 89 | return NULL; 90 | } 91 | 92 | - (NSString *)_filterMessage:(NSString *) message { 93 | if (_enableLogging) { 94 | NSLog(@"All WVJB RCVD:%@",message); 95 | } 96 | if (message&& [message isKindOfClass:[NSString class]] && [message containsString:kBridgePrefix]) 97 | { 98 | return message; 99 | } 100 | return nil; 101 | } 102 | 103 | - (void)dealloc { 104 | [self removeScriptMessageHandler]; 105 | } 106 | 107 | NSString * WebViewJavascriptBridge_js() { 108 | #define __WVJB_js_func__(x) #x 109 | 110 | // BEGIN preprocessorJSCode 111 | static NSString * preprocessorJSCode = @__WVJB_js_func__( 112 | ;(function(window) { 113 | 114 | window.WebViewJavascriptBridge = { 115 | registerHandler: registerHandler, 116 | callHandler: callHandler, 117 | _handleMessageFromObjC: _handleMessageFromObjC 118 | }; 119 | 120 | var sendMessageQueue = []; 121 | var messageHandlers = {}; 122 | var responseCallbacks = {}; 123 | var uniqueId = 1; 124 | 125 | function registerHandler(handlerName, handler) { 126 | messageHandlers[handlerName] = handler; 127 | } 128 | 129 | function callHandler(handlerName, data, responseCallback) { 130 | if (arguments.length === 2 && typeof data == 'function') { 131 | responseCallback = data; 132 | data = null; 133 | } 134 | _doSend({ handlerName:handlerName, data:data }, responseCallback); 135 | } 136 | function _doSend(message, responseCallback) { 137 | if (responseCallback) { 138 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); 139 | responseCallbacks[callbackId] = responseCallback; 140 | message['callbackId'] = callbackId; 141 | } 142 | sendMessageQueue.push(message); 143 | window.webkit.messageHandlers.pipe.postMessage('__bridge__'+ JSON.stringify(sendMessageQueue)); 144 | sendMessageQueue = []; 145 | } 146 | 147 | function _dispatchMessageFromObjC(messageJSON) { 148 | _doDispatchMessageFromObjC(); 149 | 150 | function _doDispatchMessageFromObjC() { 151 | var message = JSON.parse(messageJSON); 152 | var messageHandler; 153 | var responseCallback; 154 | 155 | if (message.responseId) { 156 | responseCallback = responseCallbacks[message.responseId]; 157 | if (!responseCallback) { 158 | 159 | return; 160 | } 161 | 162 | responseCallback(message.responseData); 163 | delete responseCallbacks[message.responseId]; 164 | } else { 165 | if (message.callbackId) { 166 | var callbackResponseId = message.callbackId; 167 | responseCallback = function(responseData) { 168 | _doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData }); 169 | }; 170 | } 171 | var handler = messageHandlers[message.handlerName]; 172 | if (!handler) { 173 | console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); 174 | } else { 175 | handler(message.data, responseCallback); 176 | } 177 | } 178 | } 179 | } 180 | function _handleMessageFromObjC(messageJSON) { 181 | _dispatchMessageFromObjC(messageJSON); 182 | } 183 | })(window); 184 | ); // END preprocessorJSCode 185 | 186 | #undef __WVJB_js_func__ 187 | return preprocessorJSCode; 188 | }; 189 | 190 | NSString * WebViewJavascriptBridge_console_log_js() { 191 | #define __WVJB_js_func__(x) #x 192 | 193 | // BEGIN preprocessorJSCode 194 | static NSString * preprocessorJSCode = @__WVJB_js_func__( 195 | ;(function(window) { 196 | let printObject = function (obj) { 197 | let output = ""; 198 | if (obj === null) { 199 | output += "null"; 200 | } 201 | else if (typeof(obj) == "undefined") { 202 | output += "undefined"; 203 | } 204 | else if (typeof obj ==='object'){ 205 | output+="{"; 206 | for(let key in obj){ 207 | let value = obj[key]; 208 | output+= "\""+key+"\""+":"+"\""+value+"\""+","; 209 | } 210 | output = output.substr(0, output.length - 1); 211 | output+="}"; 212 | } 213 | else { 214 | output = "" + obj; 215 | } 216 | return output; 217 | }; 218 | window.console.log = (function (oriLogFunc,printObject) { 219 | return function (str) { 220 | str = printObject(str); 221 | window.webkit.messageHandlers.pipe.postMessage(str); 222 | oriLogFunc.call(window.console, str); 223 | } 224 | })(window.console.log,printObject); 225 | 226 | })(window); 227 | ); // END preprocessorJSCode 228 | 229 | #undef __WVJB_js_func__ 230 | return preprocessorJSCode; 231 | }; 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.h 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | @protocol WebViewJavascriptBridgeBaseDelegate 13 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand; 14 | @end 15 | typedef NSDictionary WVJBMessage; 16 | typedef void (^WVJBResponseCallback)(id responseData); 17 | typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); 18 | 19 | @interface WebViewJavascriptBridgeBase : NSObject 20 | @property (weak, nonatomic) id delegate; 21 | @property (strong, nonatomic) NSMutableDictionary* responseCallbacks; 22 | @property (strong, nonatomic) NSMutableDictionary* messageHandlers; 23 | @property (strong, nonatomic) WVJBHandler messageHandler; 24 | 25 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; 26 | - (void)flushMessageQueue:(NSString *)messageQueueString; 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.m 3 | // TestPod 4 | // 5 | // Created by 侯森魁 on 2020/4/29. 6 | // Copyright © 2020 侯森魁. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptBridgeBase.h" 10 | @implementation WebViewJavascriptBridgeBase { 11 | long _uniqueId; 12 | } 13 | - (instancetype)init { 14 | if (self = [super init]) { 15 | self.messageHandlers = [NSMutableDictionary dictionary]; 16 | self.responseCallbacks = [NSMutableDictionary dictionary]; 17 | _uniqueId = 0; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { 23 | NSMutableDictionary* message = [NSMutableDictionary dictionary]; 24 | 25 | if (data) { 26 | message[@"data"] = data; 27 | } 28 | 29 | if (responseCallback) { 30 | NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; 31 | self.responseCallbacks[callbackId] = [responseCallback copy]; 32 | message[@"callbackId"] = callbackId; 33 | } 34 | 35 | if (handlerName) { 36 | message[@"handlerName"] = handlerName; 37 | } 38 | [self _dispatchMessage:message]; 39 | } 40 | 41 | - (void)flushMessageQueue:(NSString *)messageQueueString{ 42 | if (messageQueueString == nil || messageQueueString.length == 0) { 43 | 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."); 44 | return; 45 | } 46 | 47 | id messages = [self _deserializeMessageJSON:messageQueueString]; 48 | for (WVJBMessage* message in messages) { 49 | if (![message isKindOfClass:[WVJBMessage class]]) { 50 | NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); 51 | continue; 52 | } 53 | NSString* responseId = message[@"responseId"]; 54 | if (responseId) { 55 | WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; 56 | responseCallback(message[@"responseData"]); 57 | [self.responseCallbacks removeObjectForKey:responseId]; 58 | } else { 59 | WVJBResponseCallback responseCallback = NULL; 60 | NSString* callbackId = message[@"callbackId"]; 61 | if (callbackId) { 62 | responseCallback = ^(id responseData) { 63 | if (responseData == nil) { 64 | responseData = [NSNull null]; 65 | } 66 | 67 | WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; 68 | [self _dispatchMessage:msg]; 69 | }; 70 | } else { 71 | responseCallback = ^(id ignoreResponseData) { 72 | // Do nothing 73 | }; 74 | } 75 | 76 | WVJBHandler handler = self.messageHandlers[message[@"handlerName"]]; 77 | 78 | if (!handler) { 79 | NSLog(@"WVJBNoHandlerException, No handler for message from JS: %@", message); 80 | continue; 81 | } 82 | 83 | handler(message[@"data"], responseCallback); 84 | } 85 | } 86 | } 87 | 88 | - (NSString *)_serializeMessage:(id)message pretty:(BOOL)pretty{ 89 | return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:(NSJSONWritingOptions)(pretty ? NSJSONWritingPrettyPrinted : 0) error:nil] encoding:NSUTF8StringEncoding]; 90 | } 91 | 92 | - (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { 93 | return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; 94 | } 95 | 96 | - (void) _evaluateJavascript:(NSString *)javascriptCommand { 97 | [self.delegate _evaluateJavascript:javascriptCommand]; 98 | } 99 | 100 | - (void)_dispatchMessage:(WVJBMessage*)message { 101 | NSString *messageJSON = [self _serializeMessage:message pretty:NO]; 102 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 103 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 104 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; 105 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; 106 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; 107 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; 108 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; 109 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; 110 | 111 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; 112 | if ([[NSThread currentThread] isMainThread]) { 113 | [self _evaluateJavascript:javascriptCommand]; 114 | 115 | } else { 116 | dispatch_sync(dispatch_get_main_queue(), ^{ 117 | [self _evaluateJavascript:javascriptCommand]; 118 | }); 119 | } 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptLeakAvoider.h: -------------------------------------------------------------------------------- 1 | // 2 | // LeakAvoider.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/20. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface WebViewJavascriptLeakAvoider : NSObject 14 | @property(nonatomic,weak)id delegate; 15 | - (instancetype)initWithDelegate:(id )delegate; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /WebViewJavascriptBridge/WebViewJavascriptLeakAvoider.m: -------------------------------------------------------------------------------- 1 | // 2 | // LeakAvoider.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by 侯森魁 on 2020/4/20. 6 | // Copyright © 2020 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptLeakAvoider.h" 10 | 11 | @implementation WebViewJavascriptLeakAvoider 12 | - (instancetype)initWithDelegate:(id )delegate { 13 | if (self = [super init]) { 14 | self.delegate = delegate; 15 | } 16 | return self; 17 | } 18 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { 19 | [self.delegate userContentController:userContentController didReceiveScriptMessage:message]; 20 | } 21 | @end 22 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | xcode: 3 | version: 9.0 4 | # dependencies: 5 | # override: 6 | # - brew install kylef/formulae/swiftenv 7 | # - swiftenv install 3.0 8 | test: 9 | override: 10 | - make test-circle-ci 11 | --------------------------------------------------------------------------------