├── OC与JS交互之WebViewJavascriptBridge.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── user.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── user.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── OC与JS交互之WebViewJavascriptBridge.xcscheme │ └── xcschememanagement.plist ├── OC与JS交互之WebViewJavascriptBridge ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── WebViewJavascriptBridge │ ├── WKWebViewJavascriptBridge.h │ ├── WKWebViewJavascriptBridge.m │ ├── WebViewJavascriptBridge.h │ ├── WebViewJavascriptBridge.m │ ├── WebViewJavascriptBridgeBase.h │ ├── WebViewJavascriptBridgeBase.m │ ├── WebViewJavascriptBridge_JS.h │ └── WebViewJavascriptBridge_JS.m ├── index.html └── main.m └── README.md /OC与JS交互之WebViewJavascriptBridge.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CECE0DDE1D63FCDF007B7FE4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DDD1D63FCDF007B7FE4 /* main.m */; }; 11 | CECE0DE11D63FCDF007B7FE4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DE01D63FCDF007B7FE4 /* AppDelegate.m */; }; 12 | CECE0DE41D63FCDF007B7FE4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DE31D63FCDF007B7FE4 /* ViewController.m */; }; 13 | CECE0DE71D63FCDF007B7FE4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CECE0DE51D63FCDF007B7FE4 /* Main.storyboard */; }; 14 | CECE0DE91D63FCDF007B7FE4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CECE0DE81D63FCDF007B7FE4 /* Assets.xcassets */; }; 15 | CECE0DEC1D63FCDF007B7FE4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CECE0DEA1D63FCDF007B7FE4 /* LaunchScreen.storyboard */; }; 16 | CECE0DF41D63FDA2007B7FE4 /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = CECE0DF31D63FDA2007B7FE4 /* index.html */; }; 17 | CECE0DFE1D643855007B7FE4 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DF71D643855007B7FE4 /* WebViewJavascriptBridge.m */; }; 18 | CECE0DFF1D643855007B7FE4 /* WebViewJavascriptBridge_JS.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DF91D643855007B7FE4 /* WebViewJavascriptBridge_JS.m */; }; 19 | CECE0E001D643855007B7FE4 /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DFB1D643855007B7FE4 /* WebViewJavascriptBridgeBase.m */; }; 20 | CECE0E011D643855007B7FE4 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = CECE0DFD1D643855007B7FE4 /* WKWebViewJavascriptBridge.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | CECE0DD91D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OC与JS交互之WebViewJavascriptBridge.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | CECE0DDD1D63FCDF007B7FE4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 26 | CECE0DDF1D63FCDF007B7FE4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 27 | CECE0DE01D63FCDF007B7FE4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 28 | CECE0DE21D63FCDF007B7FE4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 29 | CECE0DE31D63FCDF007B7FE4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 30 | CECE0DE61D63FCDF007B7FE4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 31 | CECE0DE81D63FCDF007B7FE4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 32 | CECE0DEB1D63FCDF007B7FE4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 33 | CECE0DED1D63FCDF007B7FE4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | CECE0DF31D63FDA2007B7FE4 /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = ""; }; 35 | CECE0DF61D643855007B7FE4 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 36 | CECE0DF71D643855007B7FE4 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 37 | CECE0DF81D643855007B7FE4 /* WebViewJavascriptBridge_JS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge_JS.h; sourceTree = ""; }; 38 | CECE0DF91D643855007B7FE4 /* WebViewJavascriptBridge_JS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge_JS.m; sourceTree = ""; }; 39 | CECE0DFA1D643855007B7FE4 /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; 40 | CECE0DFB1D643855007B7FE4 /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; 41 | CECE0DFC1D643855007B7FE4 /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; 42 | CECE0DFD1D643855007B7FE4 /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | CECE0DD61D63FCDF007B7FE4 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | CECE0DD01D63FCDF007B7FE4 = { 57 | isa = PBXGroup; 58 | children = ( 59 | CECE0DDB1D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge */, 60 | CECE0DDA1D63FCDF007B7FE4 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | CECE0DDA1D63FCDF007B7FE4 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | CECE0DD91D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge.app */, 68 | ); 69 | name = Products; 70 | sourceTree = ""; 71 | }; 72 | CECE0DDB1D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | CECE0DF51D643855007B7FE4 /* WebViewJavascriptBridge */, 76 | CECE0DF31D63FDA2007B7FE4 /* index.html */, 77 | CECE0DDF1D63FCDF007B7FE4 /* AppDelegate.h */, 78 | CECE0DE01D63FCDF007B7FE4 /* AppDelegate.m */, 79 | CECE0DE21D63FCDF007B7FE4 /* ViewController.h */, 80 | CECE0DE31D63FCDF007B7FE4 /* ViewController.m */, 81 | CECE0DE51D63FCDF007B7FE4 /* Main.storyboard */, 82 | CECE0DE81D63FCDF007B7FE4 /* Assets.xcassets */, 83 | CECE0DEA1D63FCDF007B7FE4 /* LaunchScreen.storyboard */, 84 | CECE0DED1D63FCDF007B7FE4 /* Info.plist */, 85 | CECE0DDC1D63FCDF007B7FE4 /* Supporting Files */, 86 | ); 87 | path = "OC与JS交互之WebViewJavascriptBridge"; 88 | sourceTree = ""; 89 | }; 90 | CECE0DDC1D63FCDF007B7FE4 /* Supporting Files */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | CECE0DDD1D63FCDF007B7FE4 /* main.m */, 94 | ); 95 | name = "Supporting Files"; 96 | sourceTree = ""; 97 | }; 98 | CECE0DF51D643855007B7FE4 /* WebViewJavascriptBridge */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | CECE0DF81D643855007B7FE4 /* WebViewJavascriptBridge_JS.h */, 102 | CECE0DF91D643855007B7FE4 /* WebViewJavascriptBridge_JS.m */, 103 | CECE0DF61D643855007B7FE4 /* WebViewJavascriptBridge.h */, 104 | CECE0DF71D643855007B7FE4 /* WebViewJavascriptBridge.m */, 105 | CECE0DFA1D643855007B7FE4 /* WebViewJavascriptBridgeBase.h */, 106 | CECE0DFB1D643855007B7FE4 /* WebViewJavascriptBridgeBase.m */, 107 | CECE0DFC1D643855007B7FE4 /* WKWebViewJavascriptBridge.h */, 108 | CECE0DFD1D643855007B7FE4 /* WKWebViewJavascriptBridge.m */, 109 | ); 110 | path = WebViewJavascriptBridge; 111 | sourceTree = ""; 112 | }; 113 | /* End PBXGroup section */ 114 | 115 | /* Begin PBXNativeTarget section */ 116 | CECE0DD81D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge */ = { 117 | isa = PBXNativeTarget; 118 | buildConfigurationList = CECE0DF01D63FCDF007B7FE4 /* Build configuration list for PBXNativeTarget "OC与JS交互之WebViewJavascriptBridge" */; 119 | buildPhases = ( 120 | CECE0DD51D63FCDF007B7FE4 /* Sources */, 121 | CECE0DD61D63FCDF007B7FE4 /* Frameworks */, 122 | CECE0DD71D63FCDF007B7FE4 /* Resources */, 123 | ); 124 | buildRules = ( 125 | ); 126 | dependencies = ( 127 | ); 128 | name = "OC与JS交互之WebViewJavascriptBridge"; 129 | productName = "OC与JS交互之WebViewJavascriptBridge"; 130 | productReference = CECE0DD91D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge.app */; 131 | productType = "com.apple.product-type.application"; 132 | }; 133 | /* End PBXNativeTarget section */ 134 | 135 | /* Begin PBXProject section */ 136 | CECE0DD11D63FCDF007B7FE4 /* Project object */ = { 137 | isa = PBXProject; 138 | attributes = { 139 | LastUpgradeCheck = 0730; 140 | ORGANIZATIONNAME = rrcc; 141 | TargetAttributes = { 142 | CECE0DD81D63FCDF007B7FE4 = { 143 | CreatedOnToolsVersion = 7.3.1; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = CECE0DD41D63FCDF007B7FE4 /* Build configuration list for PBXProject "OC与JS交互之WebViewJavascriptBridge" */; 148 | compatibilityVersion = "Xcode 3.2"; 149 | developmentRegion = English; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = CECE0DD01D63FCDF007B7FE4; 156 | productRefGroup = CECE0DDA1D63FCDF007B7FE4 /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | CECE0DD81D63FCDF007B7FE4 /* OC与JS交互之WebViewJavascriptBridge */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | CECE0DD71D63FCDF007B7FE4 /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | CECE0DEC1D63FCDF007B7FE4 /* LaunchScreen.storyboard in Resources */, 171 | CECE0DF41D63FDA2007B7FE4 /* index.html in Resources */, 172 | CECE0DE91D63FCDF007B7FE4 /* Assets.xcassets in Resources */, 173 | CECE0DE71D63FCDF007B7FE4 /* Main.storyboard in Resources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXResourcesBuildPhase section */ 178 | 179 | /* Begin PBXSourcesBuildPhase section */ 180 | CECE0DD51D63FCDF007B7FE4 /* Sources */ = { 181 | isa = PBXSourcesBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | CECE0DE41D63FCDF007B7FE4 /* ViewController.m in Sources */, 185 | CECE0DFE1D643855007B7FE4 /* WebViewJavascriptBridge.m in Sources */, 186 | CECE0DE11D63FCDF007B7FE4 /* AppDelegate.m in Sources */, 187 | CECE0DDE1D63FCDF007B7FE4 /* main.m in Sources */, 188 | CECE0E001D643855007B7FE4 /* WebViewJavascriptBridgeBase.m in Sources */, 189 | CECE0DFF1D643855007B7FE4 /* WebViewJavascriptBridge_JS.m in Sources */, 190 | CECE0E011D643855007B7FE4 /* WKWebViewJavascriptBridge.m in Sources */, 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | /* End PBXSourcesBuildPhase section */ 195 | 196 | /* Begin PBXVariantGroup section */ 197 | CECE0DE51D63FCDF007B7FE4 /* Main.storyboard */ = { 198 | isa = PBXVariantGroup; 199 | children = ( 200 | CECE0DE61D63FCDF007B7FE4 /* Base */, 201 | ); 202 | name = Main.storyboard; 203 | sourceTree = ""; 204 | }; 205 | CECE0DEA1D63FCDF007B7FE4 /* LaunchScreen.storyboard */ = { 206 | isa = PBXVariantGroup; 207 | children = ( 208 | CECE0DEB1D63FCDF007B7FE4 /* Base */, 209 | ); 210 | name = LaunchScreen.storyboard; 211 | sourceTree = ""; 212 | }; 213 | /* End PBXVariantGroup section */ 214 | 215 | /* Begin XCBuildConfiguration section */ 216 | CECE0DEE1D63FCDF007B7FE4 /* Debug */ = { 217 | isa = XCBuildConfiguration; 218 | buildSettings = { 219 | ALWAYS_SEARCH_USER_PATHS = NO; 220 | CLANG_ANALYZER_NONNULL = YES; 221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 222 | CLANG_CXX_LIBRARY = "libc++"; 223 | CLANG_ENABLE_MODULES = YES; 224 | CLANG_ENABLE_OBJC_ARC = YES; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INT_CONVERSION = YES; 231 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 232 | CLANG_WARN_UNREACHABLE_CODE = YES; 233 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 234 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 235 | COPY_PHASE_STRIP = NO; 236 | DEBUG_INFORMATION_FORMAT = dwarf; 237 | ENABLE_STRICT_OBJC_MSGSEND = YES; 238 | ENABLE_TESTABILITY = YES; 239 | GCC_C_LANGUAGE_STANDARD = gnu99; 240 | GCC_DYNAMIC_NO_PIC = NO; 241 | GCC_NO_COMMON_BLOCKS = YES; 242 | GCC_OPTIMIZATION_LEVEL = 0; 243 | GCC_PREPROCESSOR_DEFINITIONS = ( 244 | "DEBUG=1", 245 | "$(inherited)", 246 | ); 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 249 | GCC_WARN_UNDECLARED_SELECTOR = YES; 250 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 251 | GCC_WARN_UNUSED_FUNCTION = YES; 252 | GCC_WARN_UNUSED_VARIABLE = YES; 253 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 254 | MTL_ENABLE_DEBUG_INFO = YES; 255 | ONLY_ACTIVE_ARCH = YES; 256 | SDKROOT = iphoneos; 257 | }; 258 | name = Debug; 259 | }; 260 | CECE0DEF1D63FCDF007B7FE4 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_ANALYZER_NONNULL = YES; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 281 | ENABLE_NS_ASSERTIONS = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu99; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 292 | MTL_ENABLE_DEBUG_INFO = NO; 293 | SDKROOT = iphoneos; 294 | VALIDATE_PRODUCT = YES; 295 | }; 296 | name = Release; 297 | }; 298 | CECE0DF11D63FCDF007B7FE4 /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | INFOPLIST_FILE = "OC与JS交互之WebViewJavascriptBridge/Info.plist"; 303 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = "com.renrencaichang.OC-JS---WebViewJavascriptBridge"; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | }; 308 | name = Debug; 309 | }; 310 | CECE0DF21D63FCDF007B7FE4 /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 314 | INFOPLIST_FILE = "OC与JS交互之WebViewJavascriptBridge/Info.plist"; 315 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 316 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 317 | PRODUCT_BUNDLE_IDENTIFIER = "com.renrencaichang.OC-JS---WebViewJavascriptBridge"; 318 | PRODUCT_NAME = "$(TARGET_NAME)"; 319 | }; 320 | name = Release; 321 | }; 322 | /* End XCBuildConfiguration section */ 323 | 324 | /* Begin XCConfigurationList section */ 325 | CECE0DD41D63FCDF007B7FE4 /* Build configuration list for PBXProject "OC与JS交互之WebViewJavascriptBridge" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | CECE0DEE1D63FCDF007B7FE4 /* Debug */, 329 | CECE0DEF1D63FCDF007B7FE4 /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | CECE0DF01D63FCDF007B7FE4 /* Build configuration list for PBXNativeTarget "OC与JS交互之WebViewJavascriptBridge" */ = { 335 | isa = XCConfigurationList; 336 | buildConfigurations = ( 337 | CECE0DF11D63FCDF007B7FE4 /* Debug */, 338 | CECE0DF21D63FCDF007B7FE4 /* Release */, 339 | ); 340 | defaultConfigurationIsVisible = 0; 341 | defaultConfigurationName = Release; 342 | }; 343 | /* End XCConfigurationList section */ 344 | }; 345 | rootObject = CECE0DD11D63FCDF007B7FE4 /* Project object */; 346 | } 347 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkStray/OC-JS-WebViewJavascriptBridge/2be67e7b38873320587aaa29c6de48289acfad04/OC与JS交互之WebViewJavascriptBridge.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge.xcodeproj/xcuserdata/user.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge.xcodeproj/xcuserdata/user.xcuserdatad/xcschemes/OC与JS交互之WebViewJavascriptBridge.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge.xcodeproj/xcuserdata/user.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | OC与JS交互之WebViewJavascriptBridge.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | CECE0DD81D63FCDF007B7FE4 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // OC与JS交互之WebViewJavascriptBridge 4 | // 5 | // Created by user on 16/8/17. 6 | // Copyright © 2016年 rrcc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // OC与JS交互之WebViewJavascriptBridge 4 | // 5 | // Created by user on 16/8/17. 6 | // Copyright © 2016年 rrcc. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 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 throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 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 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 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 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/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 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/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 | 36 | 47 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /OC与JS交互之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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // OC与JS交互之WebViewJavascriptBridge 4 | // 5 | // Created by user on 16/8/17. 6 | // Copyright © 2016年 rrcc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // OC与JS交互之WebViewJavascriptBridge 4 | // 5 | // Created by user on 16/8/17. 6 | // Copyright © 2016年 rrcc. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "WebViewJavascriptBridge.h" 11 | 12 | @interface ViewController () 13 | @property (weak, nonatomic) IBOutlet UIWebView *webView; 14 | 15 | @property (nonatomic, strong) WebViewJavascriptBridge *bridge; 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | 25 | //初始化bridge 26 | self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView]; 27 | 28 | //1 注册OC的方法给JS 29 | [self.bridge registerHandler:@"showMobile" handler:^(id data, WVJBResponseCallback responseCallback) { 30 | [self showMsg:@"我是下面的小红 手机号是:18870707070"]; 31 | }]; 32 | [self.bridge registerHandler:@"showName" handler:^(id data, WVJBResponseCallback responseCallback) { 33 | 34 | NSString *info = [NSString stringWithFormat:@"你好 %@, 很高兴见到你",data]; 35 | [self showMsg:info]; 36 | }]; 37 | [self.bridge registerHandler:@"showSendMsg" handler:^(id data, WVJBResponseCallback responseCallback) { 38 | 39 | NSDictionary *dict = (NSDictionary *)data; 40 | NSString *info = [NSString stringWithFormat:@"这是我的手机号: %@, %@ !!",dict[@"mobile"],dict[@"events"]]; 41 | 42 | [self showMsg:info]; 43 | }]; 44 | 45 | //加载webView 46 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 47 | NSURL *baseURL = [[NSBundle mainBundle] bundleURL]; 48 | [self.webView loadHTMLString:[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil] baseURL:baseURL]; 49 | } 50 | 51 | - (void)showMsg:(NSString *)msg { 52 | [[[UIAlertView alloc] initWithTitle:nil message:msg delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show]; 53 | } 54 | 55 | //2 调用JS注册给OC的方法 56 | - (IBAction)btnClick:(UIButton *)sender { 57 | if (sender.tag == 123) { 58 | [self.bridge callHandler:@"alertMobile"]; 59 | } 60 | 61 | if (sender.tag == 234) { 62 | [self.bridge callHandler:@"alertName" data:@"小红"]; 63 | } 64 | 65 | if (sender.tag == 345) { 66 | [self.bridge callHandler:@"alertSendMsg" data:@{@"mobile":@"18870707070",@"events":@"周末爬山真是件愉快的事情"}]; 67 | } 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WKWebViewJavascriptBridge.h: -------------------------------------------------------------------------------- 1 | // 2 | // WKWebViewJavascriptBridge.h 3 | // 4 | // Created by @LokiMeyburg on 10/15/14. 5 | // Copyright (c) 2014 @LokiMeyburg. All rights reserved. 6 | // 7 | 8 | #if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_1) 9 | #define supportsWKWebKit 10 | #endif 11 | 12 | #if defined(supportsWKWebKit ) 13 | 14 | #import 15 | #import "WebViewJavascriptBridgeBase.h" 16 | #import 17 | 18 | @interface WKWebViewJavascriptBridge : NSObject 19 | 20 | + (instancetype)bridgeForWebView:(WKWebView*)webView; 21 | + (void)enableLogging; 22 | 23 | - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; 24 | - (void)callHandler:(NSString*)handlerName; 25 | - (void)callHandler:(NSString*)handlerName data:(id)data; 26 | - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; 27 | - (void)reset; 28 | - (void)setWebViewDelegate:(id)webViewDelegate; 29 | 30 | @end 31 | 32 | #endif -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WKWebViewJavascriptBridge.m: -------------------------------------------------------------------------------- 1 | // 2 | // WKWebViewJavascriptBridge.m 3 | // 4 | // Created by @LokiMeyburg on 10/15/14. 5 | // Copyright (c) 2014 @LokiMeyburg. All rights reserved. 6 | // 7 | 8 | 9 | #import "WKWebViewJavascriptBridge.h" 10 | 11 | #if defined(supportsWKWebKit) 12 | 13 | @implementation WKWebViewJavascriptBridge { 14 | WKWebView* _webView; 15 | id _webViewDelegate; 16 | long _uniqueId; 17 | WebViewJavascriptBridgeBase *_base; 18 | } 19 | 20 | /* API 21 | *****/ 22 | 23 | + (void)enableLogging { [WebViewJavascriptBridgeBase enableLogging]; } 24 | 25 | + (instancetype)bridgeForWebView:(WKWebView*)webView { 26 | WKWebViewJavascriptBridge* bridge = [[self alloc] init]; 27 | [bridge _setupInstance:webView]; 28 | [bridge reset]; 29 | return bridge; 30 | } 31 | 32 | - (void)send:(id)data { 33 | [self send:data responseCallback:nil]; 34 | } 35 | 36 | - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 37 | [_base sendData:data responseCallback:responseCallback handlerName:nil]; 38 | } 39 | 40 | - (void)callHandler:(NSString *)handlerName { 41 | [self callHandler:handlerName data:nil responseCallback:nil]; 42 | } 43 | 44 | - (void)callHandler:(NSString *)handlerName data:(id)data { 45 | [self callHandler:handlerName data:data responseCallback:nil]; 46 | } 47 | 48 | - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 49 | [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; 50 | } 51 | 52 | - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { 53 | _base.messageHandlers[handlerName] = [handler copy]; 54 | } 55 | 56 | - (void)reset { 57 | [_base reset]; 58 | } 59 | 60 | - (void)setWebViewDelegate:(id)webViewDelegate { 61 | _webViewDelegate = webViewDelegate; 62 | } 63 | 64 | /* Internals 65 | ***********/ 66 | 67 | - (void)dealloc { 68 | _base = nil; 69 | _webView = nil; 70 | _webViewDelegate = nil; 71 | _webView.navigationDelegate = nil; 72 | } 73 | 74 | 75 | /* WKWebView Specific Internals 76 | ******************************/ 77 | 78 | - (void) _setupInstance:(WKWebView*)webView { 79 | _webView = webView; 80 | _webView.navigationDelegate = self; 81 | _base = [[WebViewJavascriptBridgeBase alloc] init]; 82 | _base.delegate = self; 83 | } 84 | 85 | 86 | - (void)WKFlushMessageQueue { 87 | [_webView evaluateJavaScript:[_base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) { 88 | if (error != nil) { 89 | NSLog(@"WebViewJavascriptBridge: WARNING: Error when trying to fetch data from WKWebView: %@", error); 90 | } 91 | [_base flushMessageQueue:result]; 92 | }]; 93 | } 94 | 95 | - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation 96 | { 97 | if (webView != _webView) { return; } 98 | 99 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 100 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) { 101 | [strongDelegate webView:webView didFinishNavigation:navigation]; 102 | } 103 | } 104 | 105 | 106 | - (void)webView:(WKWebView *)webView 107 | decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 108 | decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 109 | if (webView != _webView) { return; } 110 | NSURL *url = navigationAction.request.URL; 111 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 112 | 113 | if ([_base isCorrectProcotocolScheme:url]) { 114 | if ([_base isBridgeLoadedURL:url]) { 115 | [_base injectJavascriptFile]; 116 | } else if ([_base isQueueMessageURL:url]) { 117 | [self WKFlushMessageQueue]; 118 | } else { 119 | [_base logUnkownMessage:url]; 120 | } 121 | decisionHandler(WKNavigationActionPolicyCancel); 122 | } 123 | 124 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { 125 | [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; 126 | } else { 127 | decisionHandler(WKNavigationActionPolicyAllow); 128 | } 129 | } 130 | 131 | - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { 132 | if (webView != _webView) { return; } 133 | 134 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 135 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) { 136 | [strongDelegate webView:webView didStartProvisionalNavigation:navigation]; 137 | } 138 | } 139 | 140 | 141 | - (void)webView:(WKWebView *)webView 142 | didFailNavigation:(WKNavigation *)navigation 143 | withError:(NSError *)error { 144 | if (webView != _webView) { return; } 145 | 146 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 147 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) { 148 | [strongDelegate webView:webView didFailNavigation:navigation withError:error]; 149 | } 150 | } 151 | 152 | - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { 153 | if (webView != _webView) { return; } 154 | 155 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 156 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)]) { 157 | [strongDelegate webView:webView didFailProvisionalNavigation:navigation withError:error]; 158 | } 159 | } 160 | 161 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand 162 | { 163 | [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; 164 | return NULL; 165 | } 166 | 167 | 168 | 169 | @end 170 | 171 | 172 | #endif 173 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridge.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.h 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 6/14/13. 6 | // Copyright (c) 2013 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WebViewJavascriptBridgeBase.h" 11 | 12 | #if defined __MAC_OS_X_VERSION_MAX_ALLOWED 13 | #import 14 | #define WVJB_PLATFORM_OSX 15 | #define WVJB_WEBVIEW_TYPE WebView 16 | #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject 17 | #define WVJB_WEBVIEW_DELEGATE_INTERFACE NSObject 18 | #elif defined __IPHONE_OS_VERSION_MAX_ALLOWED 19 | #import 20 | #define WVJB_PLATFORM_IOS 21 | #define WVJB_WEBVIEW_TYPE UIWebView 22 | #define WVJB_WEBVIEW_DELEGATE_TYPE NSObject 23 | #define WVJB_WEBVIEW_DELEGATE_INTERFACE NSObject 24 | #endif 25 | 26 | @interface WebViewJavascriptBridge : WVJB_WEBVIEW_DELEGATE_INTERFACE 27 | 28 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView; 29 | + (void)enableLogging; 30 | + (void)setLogMaxLength:(int)length; 31 | 32 | - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; 33 | - (void)callHandler:(NSString*)handlerName; 34 | - (void)callHandler:(NSString*)handlerName data:(id)data; 35 | - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; 36 | - (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate; 37 | @end 38 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridge.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridge.m 3 | // ExampleApp-iOS 4 | // 5 | // Created by Marcus Westin on 6/14/13. 6 | // Copyright (c) 2013 Marcus Westin. All rights reserved. 7 | // 8 | 9 | #import "WebViewJavascriptBridge.h" 10 | 11 | #if __has_feature(objc_arc_weak) 12 | #define WVJB_WEAK __weak 13 | #else 14 | #define WVJB_WEAK __unsafe_unretained 15 | #endif 16 | 17 | @implementation WebViewJavascriptBridge { 18 | WVJB_WEAK WVJB_WEBVIEW_TYPE* _webView; 19 | WVJB_WEAK id _webViewDelegate; 20 | long _uniqueId; 21 | WebViewJavascriptBridgeBase *_base; 22 | } 23 | 24 | /* API 25 | *****/ 26 | 27 | + (void)enableLogging { [WebViewJavascriptBridgeBase enableLogging]; } 28 | + (void)setLogMaxLength:(int)length { [WebViewJavascriptBridgeBase setLogMaxLength:length]; } 29 | 30 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView { 31 | WebViewJavascriptBridge* bridge = [[self alloc] init]; 32 | [bridge _platformSpecificSetup:webView]; 33 | return bridge; 34 | } 35 | 36 | - (void)setWebViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate { 37 | _webViewDelegate = webViewDelegate; 38 | } 39 | 40 | - (void)send:(id)data { 41 | [self send:data responseCallback:nil]; 42 | } 43 | 44 | - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 45 | [_base sendData:data responseCallback:responseCallback handlerName:nil]; 46 | } 47 | 48 | - (void)callHandler:(NSString *)handlerName { 49 | [self callHandler:handlerName data:nil responseCallback:nil]; 50 | } 51 | 52 | - (void)callHandler:(NSString *)handlerName data:(id)data { 53 | [self callHandler:handlerName data:data responseCallback:nil]; 54 | } 55 | 56 | - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 57 | [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; 58 | } 59 | 60 | - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { 61 | _base.messageHandlers[handlerName] = [handler copy]; 62 | } 63 | 64 | /* Platform agnostic internals 65 | *****************************/ 66 | 67 | - (void)dealloc { 68 | [self _platformSpecificDealloc]; 69 | _base = nil; 70 | _webView = nil; 71 | _webViewDelegate = nil; 72 | } 73 | 74 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand 75 | { 76 | return [_webView stringByEvaluatingJavaScriptFromString:javascriptCommand]; 77 | } 78 | 79 | /* Platform specific internals: OSX 80 | **********************************/ 81 | #if defined WVJB_PLATFORM_OSX 82 | 83 | - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { 84 | _webView = webView; 85 | 86 | _webView.policyDelegate = self; 87 | 88 | _base = [[WebViewJavascriptBridgeBase alloc] init]; 89 | _base.delegate = self; 90 | } 91 | 92 | - (void) _platformSpecificDealloc { 93 | _webView.policyDelegate = nil; 94 | } 95 | 96 | - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener 97 | { 98 | if (webView != _webView) { return; } 99 | 100 | NSURL *url = [request URL]; 101 | if ([_base isCorrectProcotocolScheme:url]) { 102 | if ([_base isBridgeLoadedURL:url]) { 103 | [_base injectJavascriptFile]; 104 | } else if ([_base isQueueMessageURL:url]) { 105 | NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; 106 | [_base flushMessageQueue:messageQueueString]; 107 | } else { 108 | [_base logUnkownMessage:url]; 109 | } 110 | [listener ignore]; 111 | } else if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { 112 | [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; 113 | } else { 114 | [listener use]; 115 | } 116 | } 117 | 118 | 119 | 120 | /* Platform specific internals: iOS 121 | **********************************/ 122 | #elif defined WVJB_PLATFORM_IOS 123 | 124 | - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView { 125 | _webView = webView; 126 | _webView.delegate = self; 127 | _base = [[WebViewJavascriptBridgeBase alloc] init]; 128 | _base.delegate = self; 129 | } 130 | 131 | - (void) _platformSpecificDealloc { 132 | _webView.delegate = nil; 133 | } 134 | 135 | - (void)webViewDidFinishLoad:(UIWebView *)webView { 136 | if (webView != _webView) { return; } 137 | 138 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 139 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { 140 | [strongDelegate webViewDidFinishLoad:webView]; 141 | } 142 | } 143 | 144 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { 145 | if (webView != _webView) { return; } 146 | 147 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 148 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { 149 | [strongDelegate webView:webView didFailLoadWithError:error]; 150 | } 151 | } 152 | 153 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 154 | if (webView != _webView) { return YES; } 155 | NSURL *url = [request URL]; 156 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 157 | if ([_base isCorrectProcotocolScheme:url]) { 158 | if ([_base isBridgeLoadedURL:url]) { 159 | [_base injectJavascriptFile]; 160 | } else if ([_base isQueueMessageURL:url]) { 161 | NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; 162 | [_base flushMessageQueue:messageQueueString]; 163 | } else { 164 | [_base logUnkownMessage:url]; 165 | } 166 | return NO; 167 | } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { 168 | return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; 169 | } else { 170 | return YES; 171 | } 172 | } 173 | 174 | - (void)webViewDidStartLoad:(UIWebView *)webView { 175 | if (webView != _webView) { return; } 176 | 177 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 178 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { 179 | [strongDelegate webViewDidStartLoad:webView]; 180 | } 181 | } 182 | 183 | #endif 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.h 3 | // 4 | // Created by @LokiMeyburg on 10/15/14. 5 | // Copyright (c) 2014 @LokiMeyburg. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #define kCustomProtocolScheme @"wvjbscheme" 11 | #define kQueueHasMessage @"__WVJB_QUEUE_MESSAGE__" 12 | #define kBridgeLoaded @"__BRIDGE_LOADED__" 13 | 14 | typedef void (^WVJBResponseCallback)(id responseData); 15 | typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); 16 | typedef NSDictionary WVJBMessage; 17 | 18 | @protocol WebViewJavascriptBridgeBaseDelegate 19 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand; 20 | @end 21 | 22 | @interface WebViewJavascriptBridgeBase : NSObject 23 | 24 | 25 | @property (assign) id delegate; 26 | @property (strong, nonatomic) NSMutableArray* startupMessageQueue; 27 | @property (strong, nonatomic) NSMutableDictionary* responseCallbacks; 28 | @property (strong, nonatomic) NSMutableDictionary* messageHandlers; 29 | @property (strong, nonatomic) WVJBHandler messageHandler; 30 | 31 | + (void)enableLogging; 32 | + (void)setLogMaxLength:(int)length; 33 | - (void)reset; 34 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; 35 | - (void)flushMessageQueue:(NSString *)messageQueueString; 36 | - (void)injectJavascriptFile; 37 | - (BOOL)isCorrectProcotocolScheme:(NSURL*)url; 38 | - (BOOL)isQueueMessageURL:(NSURL*)urll; 39 | - (BOOL)isBridgeLoadedURL:(NSURL*)urll; 40 | - (void)logUnkownMessage:(NSURL*)url; 41 | - (NSString *)webViewJavascriptCheckCommand; 42 | - (NSString *)webViewJavascriptFetchQueyCommand; 43 | 44 | @end -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridgeBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewJavascriptBridgeBase.m 3 | // 4 | // Created by @LokiMeyburg on 10/15/14. 5 | // Copyright (c) 2014 @LokiMeyburg. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "WebViewJavascriptBridgeBase.h" 10 | #import "WebViewJavascriptBridge_JS.h" 11 | 12 | @implementation WebViewJavascriptBridgeBase { 13 | id _webViewDelegate; 14 | long _uniqueId; 15 | } 16 | 17 | static bool logging = false; 18 | static int logMaxLength = 500; 19 | 20 | + (void)enableLogging { logging = true; } 21 | + (void)setLogMaxLength:(int)length { logMaxLength = length;} 22 | 23 | -(id)init { 24 | self = [super init]; 25 | self.messageHandlers = [NSMutableDictionary dictionary]; 26 | self.startupMessageQueue = [NSMutableArray array]; 27 | self.responseCallbacks = [NSMutableDictionary dictionary]; 28 | _uniqueId = 0; 29 | return(self); 30 | } 31 | 32 | - (void)dealloc { 33 | self.startupMessageQueue = nil; 34 | self.responseCallbacks = nil; 35 | self.messageHandlers = nil; 36 | } 37 | 38 | - (void)reset { 39 | self.startupMessageQueue = [NSMutableArray array]; 40 | self.responseCallbacks = [NSMutableDictionary dictionary]; 41 | _uniqueId = 0; 42 | } 43 | 44 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { 45 | NSMutableDictionary* message = [NSMutableDictionary dictionary]; 46 | 47 | if (data) { 48 | message[@"data"] = data; 49 | } 50 | 51 | if (responseCallback) { 52 | NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; 53 | self.responseCallbacks[callbackId] = [responseCallback copy]; 54 | message[@"callbackId"] = callbackId; 55 | } 56 | 57 | if (handlerName) { 58 | message[@"handlerName"] = handlerName; 59 | } 60 | [self _queueMessage:message]; 61 | } 62 | 63 | - (void)flushMessageQueue:(NSString *)messageQueueString{ 64 | if (messageQueueString == nil || messageQueueString.length == 0) { 65 | 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."); 66 | return; 67 | } 68 | 69 | id messages = [self _deserializeMessageJSON:messageQueueString]; 70 | for (WVJBMessage* message in messages) { 71 | if (![message isKindOfClass:[WVJBMessage class]]) { 72 | NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); 73 | continue; 74 | } 75 | [self _log:@"RCVD" json:message]; 76 | 77 | NSString* responseId = message[@"responseId"]; 78 | if (responseId) { 79 | WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; 80 | responseCallback(message[@"responseData"]); 81 | [self.responseCallbacks removeObjectForKey:responseId]; 82 | } else { 83 | WVJBResponseCallback responseCallback = NULL; 84 | NSString* callbackId = message[@"callbackId"]; 85 | if (callbackId) { 86 | responseCallback = ^(id responseData) { 87 | if (responseData == nil) { 88 | responseData = [NSNull null]; 89 | } 90 | 91 | WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; 92 | [self _queueMessage:msg]; 93 | }; 94 | } else { 95 | responseCallback = ^(id ignoreResponseData) { 96 | // Do nothing 97 | }; 98 | } 99 | 100 | WVJBHandler handler = self.messageHandlers[message[@"handlerName"]]; 101 | 102 | if (!handler) { 103 | NSLog(@"WVJBNoHandlerException, No handler for message from JS: %@", message); 104 | continue; 105 | } 106 | 107 | handler(message[@"data"], responseCallback); 108 | } 109 | } 110 | } 111 | 112 | - (void)injectJavascriptFile { 113 | NSString *js = WebViewJavascriptBridge_js(); 114 | [self _evaluateJavascript:js]; 115 | if (self.startupMessageQueue) { 116 | NSArray* queue = self.startupMessageQueue; 117 | self.startupMessageQueue = nil; 118 | for (id queuedMessage in queue) { 119 | [self _dispatchMessage:queuedMessage]; 120 | } 121 | } 122 | } 123 | 124 | -(BOOL)isCorrectProcotocolScheme:(NSURL*)url { 125 | if([[url scheme] isEqualToString:kCustomProtocolScheme]){ 126 | return YES; 127 | } else { 128 | return NO; 129 | } 130 | } 131 | 132 | -(BOOL)isQueueMessageURL:(NSURL*)url { 133 | if([[url host] isEqualToString:kQueueHasMessage]){ 134 | return YES; 135 | } else { 136 | return NO; 137 | } 138 | } 139 | 140 | -(BOOL)isBridgeLoadedURL:(NSURL*)url { 141 | return ([[url scheme] isEqualToString:kCustomProtocolScheme] && [[url host] isEqualToString:kBridgeLoaded]); 142 | } 143 | 144 | -(void)logUnkownMessage:(NSURL*)url { 145 | NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); 146 | } 147 | 148 | -(NSString *)webViewJavascriptCheckCommand { 149 | return @"typeof WebViewJavascriptBridge == \'object\';"; 150 | } 151 | 152 | -(NSString *)webViewJavascriptFetchQueyCommand { 153 | return @"WebViewJavascriptBridge._fetchQueue();"; 154 | } 155 | 156 | // Private 157 | // ------------------------------------------- 158 | 159 | - (void) _evaluateJavascript:(NSString *)javascriptCommand { 160 | [self.delegate _evaluateJavascript:javascriptCommand]; 161 | } 162 | 163 | - (void)_queueMessage:(WVJBMessage*)message { 164 | if (self.startupMessageQueue) { 165 | [self.startupMessageQueue addObject:message]; 166 | } else { 167 | [self _dispatchMessage:message]; 168 | } 169 | } 170 | 171 | - (void)_dispatchMessage:(WVJBMessage*)message { 172 | NSString *messageJSON = [self _serializeMessage:message pretty:NO]; 173 | [self _log:@"SEND" json:messageJSON]; 174 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 175 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 176 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; 177 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; 178 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; 179 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; 180 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; 181 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; 182 | 183 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; 184 | if ([[NSThread currentThread] isMainThread]) { 185 | [self _evaluateJavascript:javascriptCommand]; 186 | 187 | } else { 188 | dispatch_sync(dispatch_get_main_queue(), ^{ 189 | [self _evaluateJavascript:javascriptCommand]; 190 | }); 191 | } 192 | } 193 | 194 | - (NSString *)_serializeMessage:(id)message pretty:(BOOL)pretty{ 195 | return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:(NSJSONWritingOptions)(pretty ? NSJSONWritingPrettyPrinted : 0) error:nil] encoding:NSUTF8StringEncoding]; 196 | } 197 | 198 | - (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { 199 | return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; 200 | } 201 | 202 | - (void)_log:(NSString *)action json:(id)json { 203 | if (!logging) { return; } 204 | if (![json isKindOfClass:[NSString class]]) { 205 | json = [self _serializeMessage:json pretty:YES]; 206 | } 207 | if ([json length] > logMaxLength) { 208 | NSLog(@"WVJB %@: %@ [...]", action, [json substringToIndex:logMaxLength]); 209 | } else { 210 | NSLog(@"WVJB %@: %@", action, json); 211 | } 212 | } 213 | 214 | @end -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NSString * WebViewJavascriptBridge_js(); -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/WebViewJavascriptBridge/WebViewJavascriptBridge_JS.m: -------------------------------------------------------------------------------- 1 | // This file contains the source for the Javascript side of the 2 | // WebViewJavascriptBridge. It is plaintext, but converted to an NSString 3 | // via some preprocessor tricks. 4 | // 5 | // Previous implementations of WebViewJavascriptBridge loaded the javascript source 6 | // from a resource. This worked fine for app developers, but library developers who 7 | // included the bridge into their library, awkwardly had to ask consumers of their 8 | // library to include the resource, violating their encapsulation. By including the 9 | // Javascript as a string resource, the encapsulation of the library is maintained. 10 | 11 | #import "WebViewJavascriptBridge_JS.h" 12 | 13 | NSString * WebViewJavascriptBridge_js() { 14 | #define __wvjb_js_func__(x) #x 15 | 16 | // BEGIN preprocessorJSCode 17 | static NSString * preprocessorJSCode = @__wvjb_js_func__( 18 | ;(function() { 19 | if (window.WebViewJavascriptBridge) { 20 | return; 21 | } 22 | window.WebViewJavascriptBridge = { 23 | registerHandler: registerHandler, 24 | callHandler: callHandler, 25 | _fetchQueue: _fetchQueue, 26 | _handleMessageFromObjC: _handleMessageFromObjC 27 | }; 28 | 29 | var messagingIframe; 30 | var sendMessageQueue = []; 31 | var messageHandlers = {}; 32 | 33 | var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'; 34 | var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__'; 35 | 36 | var responseCallbacks = {}; 37 | var uniqueId = 1; 38 | 39 | function registerHandler(handlerName, handler) { 40 | messageHandlers[handlerName] = handler; 41 | } 42 | 43 | function callHandler(handlerName, data, responseCallback) { 44 | if (arguments.length == 2 && typeof data == 'function') { 45 | responseCallback = data; 46 | data = null; 47 | } 48 | _doSend({ handlerName:handlerName, data:data }, responseCallback); 49 | } 50 | 51 | function _doSend(message, responseCallback) { 52 | if (responseCallback) { 53 | var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime(); 54 | responseCallbacks[callbackId] = responseCallback; 55 | message['callbackId'] = callbackId; 56 | } 57 | sendMessageQueue.push(message); 58 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; 59 | } 60 | 61 | function _fetchQueue() { 62 | var messageQueueString = JSON.stringify(sendMessageQueue); 63 | sendMessageQueue = []; 64 | return messageQueueString; 65 | } 66 | 67 | function _dispatchMessageFromObjC(messageJSON) { 68 | setTimeout(function _timeoutDispatchMessageFromObjC() { 69 | var message = JSON.parse(messageJSON); 70 | var messageHandler; 71 | var responseCallback; 72 | 73 | if (message.responseId) { 74 | responseCallback = responseCallbacks[message.responseId]; 75 | if (!responseCallback) { 76 | return; 77 | } 78 | responseCallback(message.responseData); 79 | delete responseCallbacks[message.responseId]; 80 | } else { 81 | if (message.callbackId) { 82 | var callbackResponseId = message.callbackId; 83 | responseCallback = function(responseData) { 84 | _doSend({ responseId:callbackResponseId, responseData:responseData }); 85 | }; 86 | } 87 | 88 | var handler = messageHandlers[message.handlerName]; 89 | try { 90 | handler(message.data, responseCallback); 91 | } catch(exception) { 92 | console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception); 93 | } 94 | if (!handler) { 95 | console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); 96 | } 97 | } 98 | }); 99 | } 100 | 101 | function _handleMessageFromObjC(messageJSON) { 102 | _dispatchMessageFromObjC(messageJSON); 103 | } 104 | 105 | messagingIframe = document.createElement('iframe'); 106 | messagingIframe.style.display = 'none'; 107 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; 108 | document.documentElement.appendChild(messagingIframe); 109 | 110 | setTimeout(_callWVJBCallbacks, 0); 111 | function _callWVJBCallbacks() { 112 | var callbacks = window.WVJBCallbacks; 113 | delete window.WVJBCallbacks; 114 | for (var i=0; i 2 | 3 | 4 | 5 | 小黄 6 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 55 | 56 | 57 |

58 | 59 |
60 | 61 |
62 |

63 | 64 | 65 |
66 | 67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 | 75 |
76 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /OC与JS交互之WebViewJavascriptBridge/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OC与JS交互之WebViewJavascriptBridge 4 | // 5 | // Created by user on 16/8/17. 6 | // Copyright © 2016年 rrcc. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OC-JS-WebViewJavascriptBridge --------------------------------------------------------------------------------