├── .gitignore ├── D3Generator.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── mozhenhua.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── D3Generator.xcscheme │ └── xcschememanagement.plist ├── D3Generator ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── D3Generator │ ├── D3Generator.h │ ├── D3Generator.m │ ├── NSObject+D3.h │ ├── NSObject+D3.m │ └── WebViewJavascriptBridge │ │ ├── WKWebViewJavascriptBridge.h │ │ ├── WKWebViewJavascriptBridge.m │ │ ├── WebViewJavascriptBridge.h │ │ ├── WebViewJavascriptBridge.js.txt │ │ ├── WebViewJavascriptBridge.m │ │ ├── WebViewJavascriptBridgeBase.h │ │ └── WebViewJavascriptBridgeBase.m ├── ExampleApp.html ├── Info.plist ├── TestViewController.h ├── TestViewController.m ├── TestViewController1.h ├── TestViewController1.m ├── TestViewController1.xib ├── TestViewController2.h ├── TestViewController2.m ├── WebViewController.h ├── WebViewController.m └── main.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | ###################### 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | *.moved-aside 15 | DerivedData 16 | */Pods/* 17 | 18 | # Cocoapods 19 | ###################### 20 | Pods/ 21 | Podfile.lock 22 | 23 | # OS generated files # 24 | ###################### 25 | .DS_Store* 26 | ehthumbs.db 27 | Icon? 28 | Thumbs.db 29 | -------------------------------------------------------------------------------- /D3Generator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 116B3C641C6477880052E864 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 116B3C631C6477880052E864 /* main.m */; }; 11 | 116B3C671C6477880052E864 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 116B3C661C6477880052E864 /* AppDelegate.m */; }; 12 | 116B3C6D1C6477880052E864 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 116B3C6B1C6477880052E864 /* Main.storyboard */; }; 13 | 116B3C6F1C6477880052E864 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 116B3C6E1C6477880052E864 /* Assets.xcassets */; }; 14 | 116B3C721C6477880052E864 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 116B3C701C6477880052E864 /* LaunchScreen.storyboard */; }; 15 | 1174D0711C65C64500A837B1 /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0701C65C64500A837B1 /* TestViewController.m */; }; 16 | 1174D0751C65C66E00A837B1 /* TestViewController1.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0731C65C66E00A837B1 /* TestViewController1.m */; }; 17 | 1174D0761C65C66E00A837B1 /* TestViewController1.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1174D0741C65C66E00A837B1 /* TestViewController1.xib */; }; 18 | 1174D0791C65C6CF00A837B1 /* TestViewController2.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0781C65C6CF00A837B1 /* TestViewController2.m */; }; 19 | 1174D07C1C65CAC700A837B1 /* NSObject+D3.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D07B1C65CAC700A837B1 /* NSObject+D3.m */; }; 20 | 1174D0851C65DEE000A837B1 /* WebViewJavascriptBridge.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1174D07F1C65DEE000A837B1 /* WebViewJavascriptBridge.js.txt */; }; 21 | 1174D0861C65DEE000A837B1 /* WebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0801C65DEE000A837B1 /* WebViewJavascriptBridge.m */; }; 22 | 1174D0871C65DEE000A837B1 /* WebViewJavascriptBridgeBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0821C65DEE000A837B1 /* WebViewJavascriptBridgeBase.m */; }; 23 | 1174D0881C65DEE000A837B1 /* WKWebViewJavascriptBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1174D0841C65DEE000A837B1 /* WKWebViewJavascriptBridge.m */; }; 24 | 11871C251C647F5E00319104 /* D3Generator.m in Sources */ = {isa = PBXBuildFile; fileRef = 11871C241C647F5E00319104 /* D3Generator.m */; }; 25 | 11871C2A1C6483C300319104 /* ExampleApp.html in Resources */ = {isa = PBXBuildFile; fileRef = 11871C291C6483C300319104 /* ExampleApp.html */; }; 26 | 11871C431C64ABE100319104 /* WebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 11871C421C64ABE100319104 /* WebViewController.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 116B3C5F1C6477880052E864 /* D3Generator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = D3Generator.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 116B3C631C6477880052E864 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | 116B3C651C6477880052E864 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | 116B3C661C6477880052E864 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | 116B3C6C1C6477880052E864 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 35 | 116B3C6E1C6477880052E864 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 36 | 116B3C711C6477880052E864 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 37 | 116B3C731C6477880052E864 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 38 | 1174D06F1C65C64500A837B1 /* TestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = ""; }; 39 | 1174D0701C65C64500A837B1 /* TestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = ""; }; 40 | 1174D0721C65C66E00A837B1 /* TestViewController1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController1.h; sourceTree = ""; }; 41 | 1174D0731C65C66E00A837B1 /* TestViewController1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController1.m; sourceTree = ""; }; 42 | 1174D0741C65C66E00A837B1 /* TestViewController1.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TestViewController1.xib; sourceTree = ""; }; 43 | 1174D0771C65C6CF00A837B1 /* TestViewController2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewController2.h; sourceTree = ""; }; 44 | 1174D0781C65C6CF00A837B1 /* TestViewController2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewController2.m; sourceTree = ""; }; 45 | 1174D07A1C65CAC700A837B1 /* NSObject+D3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+D3.h"; sourceTree = ""; }; 46 | 1174D07B1C65CAC700A837B1 /* NSObject+D3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+D3.m"; sourceTree = ""; }; 47 | 1174D07E1C65DEE000A837B1 /* WebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridge.h; sourceTree = ""; }; 48 | 1174D07F1C65DEE000A837B1 /* WebViewJavascriptBridge.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebViewJavascriptBridge.js.txt; sourceTree = ""; }; 49 | 1174D0801C65DEE000A837B1 /* WebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridge.m; sourceTree = ""; }; 50 | 1174D0811C65DEE000A837B1 /* WebViewJavascriptBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewJavascriptBridgeBase.h; sourceTree = ""; }; 51 | 1174D0821C65DEE000A837B1 /* WebViewJavascriptBridgeBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewJavascriptBridgeBase.m; sourceTree = ""; }; 52 | 1174D0831C65DEE000A837B1 /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; 53 | 1174D0841C65DEE000A837B1 /* WKWebViewJavascriptBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WKWebViewJavascriptBridge.m; sourceTree = ""; }; 54 | 11871C231C647F5E00319104 /* D3Generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = D3Generator.h; sourceTree = ""; }; 55 | 11871C241C647F5E00319104 /* D3Generator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = D3Generator.m; sourceTree = ""; }; 56 | 11871C291C6483C300319104 /* ExampleApp.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ExampleApp.html; sourceTree = ""; }; 57 | 11871C411C64ABE100319104 /* WebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewController.h; sourceTree = ""; }; 58 | 11871C421C64ABE100319104 /* WebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewController.m; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 116B3C5C1C6477880052E864 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | 116B3C561C6477880052E864 = { 73 | isa = PBXGroup; 74 | children = ( 75 | 116B3C611C6477880052E864 /* D3Generator */, 76 | 116B3C601C6477880052E864 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | 116B3C601C6477880052E864 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 116B3C5F1C6477880052E864 /* D3Generator.app */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 116B3C611C6477880052E864 /* D3Generator */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 11871C221C647F5E00319104 /* D3Generator */, 92 | 11871C291C6483C300319104 /* ExampleApp.html */, 93 | 1174D06E1C65C61900A837B1 /* TestViewController */, 94 | 116B3C651C6477880052E864 /* AppDelegate.h */, 95 | 116B3C661C6477880052E864 /* AppDelegate.m */, 96 | 11871C411C64ABE100319104 /* WebViewController.h */, 97 | 11871C421C64ABE100319104 /* WebViewController.m */, 98 | 116B3C6B1C6477880052E864 /* Main.storyboard */, 99 | 116B3C6E1C6477880052E864 /* Assets.xcassets */, 100 | 116B3C701C6477880052E864 /* LaunchScreen.storyboard */, 101 | 116B3C731C6477880052E864 /* Info.plist */, 102 | 116B3C621C6477880052E864 /* Supporting Files */, 103 | ); 104 | path = D3Generator; 105 | sourceTree = ""; 106 | }; 107 | 116B3C621C6477880052E864 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 116B3C631C6477880052E864 /* main.m */, 111 | ); 112 | name = "Supporting Files"; 113 | sourceTree = ""; 114 | }; 115 | 1174D06E1C65C61900A837B1 /* TestViewController */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 1174D06F1C65C64500A837B1 /* TestViewController.h */, 119 | 1174D0701C65C64500A837B1 /* TestViewController.m */, 120 | 1174D0721C65C66E00A837B1 /* TestViewController1.h */, 121 | 1174D0731C65C66E00A837B1 /* TestViewController1.m */, 122 | 1174D0741C65C66E00A837B1 /* TestViewController1.xib */, 123 | 1174D0771C65C6CF00A837B1 /* TestViewController2.h */, 124 | 1174D0781C65C6CF00A837B1 /* TestViewController2.m */, 125 | ); 126 | name = TestViewController; 127 | sourceTree = ""; 128 | }; 129 | 1174D07D1C65DEE000A837B1 /* WebViewJavascriptBridge */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 1174D07E1C65DEE000A837B1 /* WebViewJavascriptBridge.h */, 133 | 1174D07F1C65DEE000A837B1 /* WebViewJavascriptBridge.js.txt */, 134 | 1174D0801C65DEE000A837B1 /* WebViewJavascriptBridge.m */, 135 | 1174D0811C65DEE000A837B1 /* WebViewJavascriptBridgeBase.h */, 136 | 1174D0821C65DEE000A837B1 /* WebViewJavascriptBridgeBase.m */, 137 | 1174D0831C65DEE000A837B1 /* WKWebViewJavascriptBridge.h */, 138 | 1174D0841C65DEE000A837B1 /* WKWebViewJavascriptBridge.m */, 139 | ); 140 | path = WebViewJavascriptBridge; 141 | sourceTree = ""; 142 | }; 143 | 11871C221C647F5E00319104 /* D3Generator */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 1174D07D1C65DEE000A837B1 /* WebViewJavascriptBridge */, 147 | 11871C231C647F5E00319104 /* D3Generator.h */, 148 | 11871C241C647F5E00319104 /* D3Generator.m */, 149 | 1174D07A1C65CAC700A837B1 /* NSObject+D3.h */, 150 | 1174D07B1C65CAC700A837B1 /* NSObject+D3.m */, 151 | ); 152 | path = D3Generator; 153 | sourceTree = ""; 154 | }; 155 | /* End PBXGroup section */ 156 | 157 | /* Begin PBXNativeTarget section */ 158 | 116B3C5E1C6477880052E864 /* D3Generator */ = { 159 | isa = PBXNativeTarget; 160 | buildConfigurationList = 116B3C761C6477880052E864 /* Build configuration list for PBXNativeTarget "D3Generator" */; 161 | buildPhases = ( 162 | 116B3C5B1C6477880052E864 /* Sources */, 163 | 116B3C5C1C6477880052E864 /* Frameworks */, 164 | 116B3C5D1C6477880052E864 /* Resources */, 165 | ); 166 | buildRules = ( 167 | ); 168 | dependencies = ( 169 | ); 170 | name = D3Generator; 171 | productName = D3Generator; 172 | productReference = 116B3C5F1C6477880052E864 /* D3Generator.app */; 173 | productType = "com.apple.product-type.application"; 174 | }; 175 | /* End PBXNativeTarget section */ 176 | 177 | /* Begin PBXProject section */ 178 | 116B3C571C6477880052E864 /* Project object */ = { 179 | isa = PBXProject; 180 | attributes = { 181 | LastUpgradeCheck = 0720; 182 | ORGANIZATIONNAME = "莫振华"; 183 | TargetAttributes = { 184 | 116B3C5E1C6477880052E864 = { 185 | CreatedOnToolsVersion = 7.2; 186 | }; 187 | }; 188 | }; 189 | buildConfigurationList = 116B3C5A1C6477880052E864 /* Build configuration list for PBXProject "D3Generator" */; 190 | compatibilityVersion = "Xcode 3.2"; 191 | developmentRegion = English; 192 | hasScannedForEncodings = 0; 193 | knownRegions = ( 194 | en, 195 | Base, 196 | ); 197 | mainGroup = 116B3C561C6477880052E864; 198 | productRefGroup = 116B3C601C6477880052E864 /* Products */; 199 | projectDirPath = ""; 200 | projectRoot = ""; 201 | targets = ( 202 | 116B3C5E1C6477880052E864 /* D3Generator */, 203 | ); 204 | }; 205 | /* End PBXProject section */ 206 | 207 | /* Begin PBXResourcesBuildPhase section */ 208 | 116B3C5D1C6477880052E864 /* Resources */ = { 209 | isa = PBXResourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | 116B3C721C6477880052E864 /* LaunchScreen.storyboard in Resources */, 213 | 116B3C6F1C6477880052E864 /* Assets.xcassets in Resources */, 214 | 1174D0851C65DEE000A837B1 /* WebViewJavascriptBridge.js.txt in Resources */, 215 | 1174D0761C65C66E00A837B1 /* TestViewController1.xib in Resources */, 216 | 116B3C6D1C6477880052E864 /* Main.storyboard in Resources */, 217 | 11871C2A1C6483C300319104 /* ExampleApp.html in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 116B3C5B1C6477880052E864 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 1174D0751C65C66E00A837B1 /* TestViewController1.m in Sources */, 229 | 1174D0861C65DEE000A837B1 /* WebViewJavascriptBridge.m in Sources */, 230 | 11871C431C64ABE100319104 /* WebViewController.m in Sources */, 231 | 1174D07C1C65CAC700A837B1 /* NSObject+D3.m in Sources */, 232 | 1174D0881C65DEE000A837B1 /* WKWebViewJavascriptBridge.m in Sources */, 233 | 1174D0871C65DEE000A837B1 /* WebViewJavascriptBridgeBase.m in Sources */, 234 | 116B3C671C6477880052E864 /* AppDelegate.m in Sources */, 235 | 1174D0791C65C6CF00A837B1 /* TestViewController2.m in Sources */, 236 | 1174D0711C65C64500A837B1 /* TestViewController.m in Sources */, 237 | 11871C251C647F5E00319104 /* D3Generator.m in Sources */, 238 | 116B3C641C6477880052E864 /* main.m in Sources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | /* End PBXSourcesBuildPhase section */ 243 | 244 | /* Begin PBXVariantGroup section */ 245 | 116B3C6B1C6477880052E864 /* Main.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 116B3C6C1C6477880052E864 /* Base */, 249 | ); 250 | name = Main.storyboard; 251 | sourceTree = ""; 252 | }; 253 | 116B3C701C6477880052E864 /* LaunchScreen.storyboard */ = { 254 | isa = PBXVariantGroup; 255 | children = ( 256 | 116B3C711C6477880052E864 /* Base */, 257 | ); 258 | name = LaunchScreen.storyboard; 259 | sourceTree = ""; 260 | }; 261 | /* End PBXVariantGroup section */ 262 | 263 | /* Begin XCBuildConfiguration section */ 264 | 116B3C741C6477880052E864 /* Debug */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | ALWAYS_SEARCH_USER_PATHS = NO; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 282 | COPY_PHASE_STRIP = NO; 283 | DEBUG_INFORMATION_FORMAT = dwarf; 284 | ENABLE_STRICT_OBJC_MSGSEND = YES; 285 | ENABLE_TESTABILITY = YES; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_DYNAMIC_NO_PIC = NO; 288 | GCC_NO_COMMON_BLOCKS = YES; 289 | GCC_OPTIMIZATION_LEVEL = 0; 290 | GCC_PREPROCESSOR_DEFINITIONS = ( 291 | "DEBUG=1", 292 | "$(inherited)", 293 | ); 294 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 295 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 296 | GCC_WARN_UNDECLARED_SELECTOR = YES; 297 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 298 | GCC_WARN_UNUSED_FUNCTION = YES; 299 | GCC_WARN_UNUSED_VARIABLE = YES; 300 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 301 | MTL_ENABLE_DEBUG_INFO = YES; 302 | ONLY_ACTIVE_ARCH = YES; 303 | SDKROOT = iphoneos; 304 | }; 305 | name = Debug; 306 | }; 307 | 116B3C751C6477880052E864 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 312 | CLANG_CXX_LIBRARY = "libc++"; 313 | CLANG_ENABLE_MODULES = YES; 314 | CLANG_ENABLE_OBJC_ARC = YES; 315 | CLANG_WARN_BOOL_CONVERSION = YES; 316 | CLANG_WARN_CONSTANT_CONVERSION = YES; 317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 318 | CLANG_WARN_EMPTY_BODY = YES; 319 | CLANG_WARN_ENUM_CONVERSION = YES; 320 | CLANG_WARN_INT_CONVERSION = YES; 321 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 325 | COPY_PHASE_STRIP = NO; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu99; 330 | GCC_NO_COMMON_BLOCKS = YES; 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 = 9.2; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | SDKROOT = iphoneos; 340 | VALIDATE_PRODUCT = YES; 341 | }; 342 | name = Release; 343 | }; 344 | 116B3C771C6477880052E864 /* Debug */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 348 | INFOPLIST_FILE = D3Generator/Info.plist; 349 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 350 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 351 | PRODUCT_BUNDLE_IDENTIFIER = com.d3.D3Generator; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | }; 354 | name = Debug; 355 | }; 356 | 116B3C781C6477880052E864 /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 360 | INFOPLIST_FILE = D3Generator/Info.plist; 361 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 362 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 363 | PRODUCT_BUNDLE_IDENTIFIER = com.d3.D3Generator; 364 | PRODUCT_NAME = "$(TARGET_NAME)"; 365 | }; 366 | name = Release; 367 | }; 368 | /* End XCBuildConfiguration section */ 369 | 370 | /* Begin XCConfigurationList section */ 371 | 116B3C5A1C6477880052E864 /* Build configuration list for PBXProject "D3Generator" */ = { 372 | isa = XCConfigurationList; 373 | buildConfigurations = ( 374 | 116B3C741C6477880052E864 /* Debug */, 375 | 116B3C751C6477880052E864 /* Release */, 376 | ); 377 | defaultConfigurationIsVisible = 0; 378 | defaultConfigurationName = Release; 379 | }; 380 | 116B3C761C6477880052E864 /* Build configuration list for PBXNativeTarget "D3Generator" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | 116B3C771C6477880052E864 /* Debug */, 384 | 116B3C781C6477880052E864 /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | /* End XCConfigurationList section */ 390 | }; 391 | rootObject = 116B3C571C6477880052E864 /* Project object */; 392 | } 393 | -------------------------------------------------------------------------------- /D3Generator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /D3Generator.xcodeproj/xcuserdata/mozhenhua.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /D3Generator.xcodeproj/xcuserdata/mozhenhua.xcuserdatad/xcschemes/D3Generator.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 | -------------------------------------------------------------------------------- /D3Generator.xcodeproj/xcuserdata/mozhenhua.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | D3Generator.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 116B3C5E1C6477880052E864 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /D3Generator/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/5. 6 | // Copyright © 2016年 莫振华. 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 | -------------------------------------------------------------------------------- /D3Generator/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/5. 6 | // Copyright © 2016年 莫振华. 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 | -------------------------------------------------------------------------------- /D3Generator/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 | } -------------------------------------------------------------------------------- /D3Generator/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 | -------------------------------------------------------------------------------- /D3Generator/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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/D3Generator.h: -------------------------------------------------------------------------------- 1 | // 2 | // D3Generator.h 3 | // mdcnapp 4 | // 5 | // Created by 莫振华 on 16/2/4. 6 | // Copyright © 2016年 mozhenhau. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface D3Generator : NSObject 13 | 14 | 15 | +(UIViewController*)createViewControllerWithDict:(NSDictionary*)dict; 16 | 17 | 18 | +(UIViewController*)createViewControllerWithDictAndPush:(NSDictionary*)dict; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/D3Generator.m: -------------------------------------------------------------------------------- 1 | // 2 | // D3Generator.m 3 | // mdcnapp 4 | // 5 | // Created by 莫振华 on 16/2/4. 6 | // Copyright © 2016年 mozhenhau. All rights reserved. 7 | // 对象生成器工厂 8 | 9 | #import "D3Generator.h" 10 | #import // 导入运行时文件 11 | #import "NSObject+D3.h" 12 | 13 | @implementation D3Generator 14 | 15 | 16 | /** 17 | * 根据字典生成viewcontroller 18 | * 19 | * @param dict 字典 20 | * 21 | * @return UIViewController 22 | */ 23 | +(UIViewController*)createViewControllerWithDict:(NSDictionary*)dict{ 24 | if (dict[@"storyboard"]) { 25 | UIStoryboard* storyboard = [UIStoryboard storyboardWithName:dict[@"storyboard"] bundle:nil]; 26 | UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:dict[@"className"]]; //记得在storyboard的Storyboard ID改成对应的className 27 | [vc setPropertiesWithDict:dict]; 28 | return vc; 29 | } 30 | else{ 31 | UIViewController *vc = [NSObject objectWithDict:dict]; 32 | return vc; 33 | } 34 | } 35 | 36 | /** 37 | * 根据字典生成viewcontroller 并自行跳转到vc。 38 | * 所在vc为navigation中则pop到根页并push。 39 | * 所在vc为基本viewcontroller则直接present 40 | * 41 | * @param dict 字典 42 | */ 43 | +(UIViewController*)createViewControllerWithDictAndPush:(NSDictionary*)dict{ 44 | UIViewController *vc = [self createViewControllerWithDict:dict]; 45 | if (!vc) { 46 | return nil; 47 | } 48 | 49 | 50 | UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController; 51 | 52 | if ([rootVC isKindOfClass:[UITabBarController class]]) { //root为tabbar 53 | UITabBarController *tabVC = (UITabBarController *)rootVC; 54 | UIViewController *tabRootVC = tabVC.viewControllers[tabVC.selectedIndex]; 55 | if ([tabRootVC isKindOfClass:[UINavigationController class]]) { //tabbar的root为navigation 56 | [(UINavigationController *)tabRootVC pushViewController:vc animated:YES]; 57 | } 58 | else{ 59 | [tabRootVC presentViewController:vc animated:YES completion:nil]; 60 | } 61 | } 62 | else if([rootVC isKindOfClass:[UINavigationController class]]){ //root为navigation 63 | [(UINavigationController*)rootVC pushViewController:vc animated:YES]; 64 | } 65 | else{ //root为uiviewcontroller 66 | [rootVC presentViewController:vc animated:YES completion:nil]; 67 | } 68 | return rootVC; 69 | } 70 | @end 71 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/NSObject+D3.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+D3.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import 10 | #import // 导入运行时文件 11 | 12 | @interface NSObject (D3) 13 | 14 | //通过字典生成对象, 根据字典的className决定生成 15 | +(id)objectWithDict:(NSDictionary*)dict; 16 | 17 | //设置对象属性值 18 | -(void)setPropertiesWithDict:(NSDictionary*)dict; 19 | 20 | //获取对象属性名 21 | - (NSMutableArray*)getProperties; 22 | - (NSMutableArray*)getPropertiesWithClass:(Class)cls; 23 | 24 | 25 | #pragma mark swizzle 26 | + (BOOL)swizzleMethod:(SEL)oldSel withMethod:(SEL)newSel withTarget:(id)target; 27 | @end 28 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/NSObject+D3.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+D3.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import "NSObject+D3.h" 10 | 11 | @implementation NSObject(D3) 12 | 13 | /** 14 | * 根据字典生成对象,目前只支持基本类型 15 | * 根据字典的className决定生成 16 | * @param dict 字典 17 | * 18 | * @return id 19 | */ 20 | +(id)objectWithDict:(NSDictionary*)dict{ 21 | if (!dict || !dict[@"className"]) { 22 | return nil; 23 | } 24 | 25 | Class class = NSClassFromString(dict[@"className"]); 26 | id object = [[class alloc]init]; 27 | [self setPropertiesWithDict:dict object:object]; 28 | return object; 29 | } 30 | 31 | /** 32 | * 根据字段设置对象的属性,支持基础属性 33 | * 34 | * @param dict 字典 35 | * @param object 要设置的对象 36 | */ 37 | -(void)setPropertiesWithDict:(NSDictionary*)dict object:(id)object{ 38 | Class class; 39 | if (dict[@"className"]) { 40 | class = NSClassFromString(dict[@"className"]); 41 | } 42 | else{ 43 | class = self.class; 44 | } 45 | 46 | NSArray *properties = [self getPropertiesWithClass:class]; 47 | for (NSString* key in properties) { 48 | if (dict[key]) { 49 | [object setValue:dict[key] forKey:key]; 50 | } 51 | } 52 | } 53 | 54 | 55 | -(void)setPropertiesWithDict:(NSDictionary*)dict{ 56 | [self setPropertiesWithDict:dict object:self]; 57 | } 58 | 59 | 60 | 61 | /** 62 | * 获取某个类的所有字段名 63 | * 64 | * @param cls 要获取的类class 65 | * 66 | * @return 返回一个数组 67 | */ 68 | - (NSMutableArray*)getPropertiesWithClass:(Class)cls{ 69 | // 获取当前类的所有属性 70 | unsigned int count;// 记录属性个数 71 | objc_property_t *properties = class_copyPropertyList(cls, &count); 72 | // 遍历 73 | NSMutableArray *mArray = [NSMutableArray array]; 74 | for (int i = 0; i < count; i++) { 75 | // objc_property_t 属性类型 76 | objc_property_t property = properties[i]; 77 | // 获取属性的名称 C语言字符串 78 | const char *cName = property_getName(property); 79 | // 转换为Objective C 字符串 80 | NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding]; 81 | [mArray addObject:name]; 82 | } 83 | return mArray.copy; 84 | } 85 | 86 | - (NSMutableArray*)getProperties{ 87 | return [self getPropertiesWithClass:self.class]; 88 | } 89 | 90 | 91 | #pragma mark swizzle 92 | + (BOOL)swizzleMethod:(SEL)oldSel withMethod:(SEL)newSel withTarget:(id)target{ 93 | Method newMethod = class_getInstanceMethod([target class], newSel); 94 | if (newMethod 95 | && class_replaceMethod(self.class, oldSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) { 96 | 97 | return YES; 98 | } 99 | return NO; 100 | } 101 | @end 102 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/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 handler:(WVJBHandler)handler; 21 | + (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)handler; 22 | + (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; 23 | + (void)enableLogging; 24 | 25 | - (void)send:(id)message; 26 | - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; 27 | - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; 28 | - (void)callHandler:(NSString*)handlerName; 29 | - (void)callHandler:(NSString*)handlerName data:(id)data; 30 | - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; 31 | - (void)reset; 32 | 33 | @end 34 | 35 | #endif -------------------------------------------------------------------------------- /D3Generator/D3Generator/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 handler:(WVJBHandler)handler { 26 | return [self bridgeForWebView:webView webViewDelegate:nil handler:handler]; 27 | } 28 | 29 | + (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)messageHandler { 30 | return [self bridgeForWebView:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:nil]; 31 | } 32 | 33 | + (instancetype)bridgeForWebView:(WKWebView*)webView webViewDelegate:(NSObject*)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle 34 | { 35 | WKWebViewJavascriptBridge* bridge = [[self alloc] init]; 36 | [bridge _setupInstance:webView webViewDelegate:webViewDelegate handler:messageHandler resourceBundle:bundle]; 37 | [bridge reset]; 38 | return bridge; 39 | } 40 | 41 | - (void)send:(id)data { 42 | [self send:data responseCallback:nil]; 43 | } 44 | 45 | - (void)send:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 46 | [_base sendData:data responseCallback:responseCallback handlerName:nil]; 47 | } 48 | 49 | - (void)callHandler:(NSString *)handlerName { 50 | [self callHandler:handlerName data:nil responseCallback:nil]; 51 | } 52 | 53 | - (void)callHandler:(NSString *)handlerName data:(id)data { 54 | [self callHandler:handlerName data:data responseCallback:nil]; 55 | } 56 | 57 | - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback { 58 | [_base sendData:data responseCallback:responseCallback handlerName:handlerName]; 59 | } 60 | 61 | - (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler { 62 | _base.messageHandlers[handlerName] = [handler copy]; 63 | } 64 | 65 | - (void)reset { 66 | [_base reset]; 67 | } 68 | 69 | /* Internals 70 | ***********/ 71 | 72 | - (void)dealloc { 73 | _base = nil; 74 | _webView = nil; 75 | _webViewDelegate = nil; 76 | _webView.navigationDelegate = nil; 77 | } 78 | 79 | 80 | /* WKWebView Specific Internals 81 | ******************************/ 82 | 83 | - (void) _setupInstance:(WKWebView*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{ 84 | _webView = webView; 85 | _webViewDelegate = webViewDelegate; 86 | _webView.navigationDelegate = self; 87 | _base = [[WebViewJavascriptBridgeBase alloc] initWithHandler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle]; 88 | _base.delegate = self; 89 | } 90 | 91 | 92 | - (void)WKFlushMessageQueue { 93 | [_webView evaluateJavaScript:[_base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) { 94 | [_base flushMessageQueue:result]; 95 | }]; 96 | } 97 | 98 | - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation 99 | { 100 | if (webView != _webView) { return; } 101 | 102 | _base.numRequestsLoading--; 103 | 104 | if (_base.numRequestsLoading == 0) { 105 | [webView evaluateJavaScript:[_base webViewJavascriptCheckCommand] completionHandler:^(NSString *result, NSError *error) { 106 | [_base injectJavascriptFile:![result boolValue]]; 107 | }]; 108 | } 109 | 110 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 111 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFinishNavigation:)]) { 112 | [strongDelegate webView:webView didFinishNavigation:navigation]; 113 | } 114 | } 115 | 116 | 117 | - (void)webView:(WKWebView *)webView 118 | decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 119 | decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 120 | if (webView != _webView) { return; } 121 | NSURL *url = navigationAction.request.URL; 122 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 123 | 124 | if ([_base isCorrectProcotocolScheme:url]) { 125 | if ([_base isCorrectHost:url]) { 126 | [self WKFlushMessageQueue]; 127 | } else { 128 | [_base logUnkownMessage:url]; 129 | } 130 | [webView stopLoading]; 131 | } 132 | 133 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) { 134 | [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler]; 135 | } else { 136 | decisionHandler(WKNavigationActionPolicyAllow); 137 | } 138 | } 139 | 140 | - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { 141 | if (webView != _webView) { return; } 142 | 143 | _base.numRequestsLoading++; 144 | 145 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 146 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)]) { 147 | [strongDelegate webView:webView didStartProvisionalNavigation:navigation]; 148 | } 149 | } 150 | 151 | 152 | - (void)webView:(WKWebView *)webView 153 | didFailNavigation:(WKNavigation *)navigation 154 | withError:(NSError *)error { 155 | if (webView != _webView) { return; } 156 | 157 | _base.numRequestsLoading--; 158 | 159 | __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate; 160 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailNavigation:withError:)]) { 161 | [strongDelegate webView:webView didFailNavigation:navigation withError:error]; 162 | } 163 | } 164 | 165 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand 166 | { 167 | [_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; 168 | return NULL; 169 | } 170 | 171 | 172 | 173 | @end 174 | 175 | 176 | #endif 177 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/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 handler:(WVJBHandler)handler; 29 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; 30 | + (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle; 31 | + (void)enableLogging; 32 | 33 | - (void)send:(id)message; 34 | - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback; 35 | - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler; 36 | - (void)callHandler:(NSString*)handlerName; 37 | - (void)callHandler:(NSString*)handlerName data:(id)data; 38 | - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/WebViewJavascriptBridge/WebViewJavascriptBridge.js.txt: -------------------------------------------------------------------------------- 1 | ;(function() { 2 | if (window.WebViewJavascriptBridge) { return } 3 | var messagingIframe 4 | var sendMessageQueue = [] 5 | var receiveMessageQueue = [] 6 | var messageHandlers = {} 7 | 8 | var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme' 9 | var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__' 10 | 11 | var responseCallbacks = {} 12 | var uniqueId = 1 13 | 14 | function _createQueueReadyIframe(doc) { 15 | messagingIframe = doc.createElement('iframe') 16 | messagingIframe.style.display = 'none' 17 | messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE 18 | doc.documentElement.appendChild(messagingIframe) 19 | } 20 | 21 | function init(messageHandler) { 22 | if (WebViewJavascriptBridge._messageHandler) { throw new Error('WebViewJavascriptBridge.init called twice') } 23 | WebViewJavascriptBridge._messageHandler = messageHandler 24 | var receivedMessages = receiveMessageQueue 25 | receiveMessageQueue = null 26 | for (var i=0; i)listener 133 | { 134 | if (webView != _webView) { return; } 135 | 136 | NSURL *url = [request URL]; 137 | if ([_base isCorrectProcotocolScheme:url]) { 138 | if ([_base isCorrectHost:url]) { 139 | NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; 140 | [_base flushMessageQueue:messageQueueString]; 141 | } else { 142 | [_base logUnkownMessage:url]; 143 | } 144 | [listener ignore]; 145 | } else if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) { 146 | [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener]; 147 | } else { 148 | [listener use]; 149 | } 150 | } 151 | 152 | - (void)webView:(WebView *)webView didCommitLoadForFrame:(WebFrame *)frame { 153 | if (webView != _webView) { return; } 154 | 155 | if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:didCommitLoadForFrame:)]) { 156 | [_webViewDelegate webView:webView didCommitLoadForFrame:frame]; 157 | } 158 | } 159 | 160 | - (NSURLRequest *)webView:(WebView *)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { 161 | if (webView != _webView) { return request; } 162 | 163 | if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)]) { 164 | return [_webViewDelegate webView:webView resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:dataSource]; 165 | } 166 | 167 | return request; 168 | } 169 | 170 | 171 | 172 | /* Platform specific internals: iOS 173 | **********************************/ 174 | #elif defined WVJB_PLATFORM_IOS 175 | 176 | - (void) _platformSpecificSetup:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(id)webViewDelegate handler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle{ 177 | _webView = webView; 178 | _webView.delegate = self; 179 | _webViewDelegate = webViewDelegate; 180 | _base = [[WebViewJavascriptBridgeBase alloc] initWithHandler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle]; 181 | _base.delegate = self; 182 | } 183 | 184 | - (void) _platformSpecificDealloc { 185 | _webView.delegate = nil; 186 | } 187 | 188 | - (void)webViewDidFinishLoad:(UIWebView *)webView { 189 | if (webView != _webView) { return; } 190 | 191 | _numRequestsLoading--; 192 | 193 | if (_numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:[_base webViewJavascriptCheckCommand]] isEqualToString:@"true"]) { 194 | [_base injectJavascriptFile:YES]; 195 | } 196 | [_base dispatchStartUpMessageQueue]; 197 | 198 | 199 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 200 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { 201 | [strongDelegate webViewDidFinishLoad:webView]; 202 | } 203 | } 204 | 205 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { 206 | if (webView != _webView) { return; } 207 | 208 | _numRequestsLoading--; 209 | 210 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 211 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { 212 | [strongDelegate webView:webView didFailLoadWithError:error]; 213 | } 214 | } 215 | 216 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 217 | if (webView != _webView) { return YES; } 218 | NSURL *url = [request URL]; 219 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 220 | if ([_base isCorrectProcotocolScheme:url]) { 221 | if ([_base isCorrectHost:url]) { 222 | NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]]; 223 | [_base flushMessageQueue:messageQueueString]; 224 | } else { 225 | [_base logUnkownMessage:url]; 226 | } 227 | return NO; 228 | } else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { 229 | return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; 230 | } else { 231 | return YES; 232 | } 233 | } 234 | 235 | - (void)webViewDidStartLoad:(UIWebView *)webView { 236 | if (webView != _webView) { return; } 237 | 238 | _numRequestsLoading++; 239 | 240 | __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate; 241 | if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) { 242 | [strongDelegate webViewDidStartLoad:webView]; 243 | } 244 | } 245 | 246 | #endif 247 | 248 | @end 249 | -------------------------------------------------------------------------------- /D3Generator/D3Generator/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 | 13 | typedef void (^WVJBResponseCallback)(id responseData); 14 | typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback); 15 | typedef NSDictionary WVJBMessage; 16 | 17 | @protocol WebViewJavascriptBridgeBaseDelegate 18 | - (NSString*) _evaluateJavascript:(NSString*)javascriptCommand; 19 | @end 20 | 21 | @interface WebViewJavascriptBridgeBase : NSObject 22 | 23 | 24 | @property (assign) id delegate; 25 | @property (strong, nonatomic) NSMutableArray* startupMessageQueue; 26 | @property (strong, nonatomic) NSMutableDictionary* responseCallbacks; 27 | @property (strong, nonatomic) NSMutableDictionary* messageHandlers; 28 | @property (strong, nonatomic) WVJBHandler messageHandler; 29 | @property NSUInteger numRequestsLoading; 30 | 31 | + (void)enableLogging; 32 | - (id)initWithHandler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle; 33 | - (void)reset; 34 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName; 35 | - (void)flushMessageQueue:(NSString *)messageQueueString; 36 | - (void)injectJavascriptFile:(BOOL)shouldInject; 37 | - (BOOL)isCorrectProcotocolScheme:(NSURL*)url; 38 | - (BOOL)isCorrectHost:(NSURL*)urll; 39 | - (void)logUnkownMessage:(NSURL*)url; 40 | - (void)dispatchStartUpMessageQueue; 41 | - (NSString *)webViewJavascriptCheckCommand; 42 | - (NSString *)webViewJavascriptFetchQueyCommand; 43 | 44 | @end -------------------------------------------------------------------------------- /D3Generator/D3Generator/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 | 11 | @implementation WebViewJavascriptBridgeBase { 12 | id _webViewDelegate; 13 | long _uniqueId; 14 | NSBundle *_resourceBundle; 15 | } 16 | 17 | static bool logging = false; 18 | 19 | + (void)enableLogging { logging = true; } 20 | 21 | -(id)initWithHandler:(WVJBHandler)messageHandler resourceBundle:(NSBundle*)bundle 22 | { 23 | self = [super init]; 24 | _resourceBundle = bundle; 25 | self.messageHandler = messageHandler; 26 | self.messageHandlers = [NSMutableDictionary dictionary]; 27 | self.startupMessageQueue = [NSMutableArray array]; 28 | self.responseCallbacks = [NSMutableDictionary dictionary]; 29 | _uniqueId = 0; 30 | return(self); 31 | } 32 | 33 | - (void)dealloc { 34 | self.startupMessageQueue = nil; 35 | self.responseCallbacks = nil; 36 | self.messageHandlers = nil; 37 | self.messageHandler = nil; 38 | } 39 | 40 | - (void)reset { 41 | self.startupMessageQueue = [NSMutableArray array]; 42 | self.responseCallbacks = [NSMutableDictionary dictionary]; 43 | _uniqueId = 0; 44 | } 45 | 46 | - (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName { 47 | NSMutableDictionary* message = [NSMutableDictionary dictionary]; 48 | 49 | if (data) { 50 | message[@"data"] = data; 51 | } 52 | 53 | if (responseCallback) { 54 | NSString* callbackId = [NSString stringWithFormat:@"objc_cb_%ld", ++_uniqueId]; 55 | self.responseCallbacks[callbackId] = [responseCallback copy]; 56 | message[@"callbackId"] = callbackId; 57 | } 58 | 59 | if (handlerName) { 60 | message[@"handlerName"] = handlerName; 61 | } 62 | [self _queueMessage:message]; 63 | } 64 | 65 | - (void)flushMessageQueue:(NSString *)messageQueueString{ 66 | id messages = [self _deserializeMessageJSON:messageQueueString]; 67 | if (![messages isKindOfClass:[NSArray class]]) { 68 | NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messages class], messages); 69 | return; 70 | } 71 | for (WVJBMessage* message in messages) { 72 | if (![message isKindOfClass:[WVJBMessage class]]) { 73 | NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); 74 | continue; 75 | } 76 | [self _log:@"RCVD" json:message]; 77 | 78 | NSString* responseId = message[@"responseId"]; 79 | if (responseId) { 80 | WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; 81 | responseCallback(message[@"responseData"]); 82 | [self.responseCallbacks removeObjectForKey:responseId]; 83 | } else { 84 | WVJBResponseCallback responseCallback = NULL; 85 | NSString* callbackId = message[@"callbackId"]; 86 | if (callbackId) { 87 | responseCallback = ^(id responseData) { 88 | if (responseData == nil) { 89 | responseData = [NSNull null]; 90 | } 91 | 92 | WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; 93 | [self _queueMessage:msg]; 94 | }; 95 | } else { 96 | responseCallback = ^(id ignoreResponseData) { 97 | // Do nothing 98 | }; 99 | } 100 | 101 | WVJBHandler handler; 102 | if (message[@"handlerName"]) { 103 | handler = self.messageHandlers[message[@"handlerName"]]; 104 | } else { 105 | handler = self.messageHandler; 106 | } 107 | 108 | if (!handler) { 109 | [NSException raise:@"WVJBNoHandlerException" format:@"No handler for message from JS: %@", message]; 110 | } 111 | 112 | handler(message[@"data"], responseCallback); 113 | } 114 | } 115 | } 116 | 117 | - (void)injectJavascriptFile:(BOOL)shouldInject { 118 | if(shouldInject){ 119 | NSBundle *bundle = _resourceBundle ? _resourceBundle : [NSBundle mainBundle]; 120 | NSString *filePath = [bundle pathForResource:@"WebViewJavascriptBridge.js" ofType:@"txt"]; 121 | NSString *js = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; 122 | [self _evaluateJavascript:js]; 123 | [self dispatchStartUpMessageQueue]; 124 | } 125 | 126 | } 127 | 128 | - (void)dispatchStartUpMessageQueue { 129 | if (self.startupMessageQueue) { 130 | for (id queuedMessage in self.startupMessageQueue) { 131 | [self _dispatchMessage:queuedMessage]; 132 | } 133 | self.startupMessageQueue = nil; 134 | } 135 | } 136 | 137 | -(BOOL)isCorrectProcotocolScheme:(NSURL*)url { 138 | if([[url scheme] isEqualToString:kCustomProtocolScheme]){ 139 | return YES; 140 | } else { 141 | return NO; 142 | } 143 | } 144 | 145 | -(BOOL)isCorrectHost:(NSURL*)url { 146 | if([[url host] isEqualToString:kQueueHasMessage]){ 147 | return YES; 148 | } else { 149 | return NO; 150 | } 151 | } 152 | 153 | -(void)logUnkownMessage:(NSURL*)url { 154 | NSLog(@"WebViewJavascriptBridge: WARNING: Received unknown WebViewJavascriptBridge command %@://%@", kCustomProtocolScheme, [url path]); 155 | } 156 | 157 | -(NSString *)webViewJavascriptCheckCommand { 158 | return @"typeof WebViewJavascriptBridge == \'object\';"; 159 | } 160 | 161 | -(NSString *)webViewJavascriptFetchQueyCommand { 162 | return @"WebViewJavascriptBridge._fetchQueue();"; 163 | } 164 | 165 | // Private 166 | // ------------------------------------------- 167 | 168 | - (void) _evaluateJavascript:(NSString *)javascriptCommand { 169 | [self.delegate _evaluateJavascript:javascriptCommand]; 170 | } 171 | 172 | - (void)_queueMessage:(WVJBMessage*)message { 173 | if (self.startupMessageQueue) { 174 | [self.startupMessageQueue addObject:message]; 175 | } else { 176 | [self _dispatchMessage:message]; 177 | } 178 | } 179 | 180 | - (void)_dispatchMessage:(WVJBMessage*)message { 181 | NSString *messageJSON = [self _serializeMessage:message]; 182 | [self _log:@"SEND" json:messageJSON]; 183 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 184 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 185 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; 186 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; 187 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; 188 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; 189 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028" withString:@"\\u2028"]; 190 | messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\\u2029"]; 191 | 192 | NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON]; 193 | if ([[NSThread currentThread] isMainThread]) { 194 | [self _evaluateJavascript:javascriptCommand]; 195 | 196 | } else { 197 | dispatch_sync(dispatch_get_main_queue(), ^{ 198 | [self _evaluateJavascript:javascriptCommand]; 199 | }); 200 | } 201 | } 202 | 203 | - (NSString *)_serializeMessage:(id)message { 204 | return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:message options:0 error:nil] encoding:NSUTF8StringEncoding]; 205 | } 206 | 207 | - (NSArray*)_deserializeMessageJSON:(NSString *)messageJSON { 208 | return [NSJSONSerialization JSONObjectWithData:[messageJSON dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; 209 | } 210 | 211 | - (void)_log:(NSString *)action json:(id)json { 212 | if (!logging) { return; } 213 | if (![json isKindOfClass:[NSString class]]) { 214 | json = [self _serializeMessage:json]; 215 | } 216 | if ([json length] > 500) { 217 | NSLog(@"WVJB %@: %@ [...]", action, [json substringToIndex:500]); 218 | } else { 219 | NSLog(@"WVJB %@: %@", action, json); 220 | } 221 | } 222 | 223 | @end -------------------------------------------------------------------------------- /D3Generator/ExampleApp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

我是UIWebview

5 | 27 |
Go VC1, 跳转到纯代码写的vc

28 |
Go VC2, 跳转到xib写的vc

29 |
Go VC3, 跳转到storyboard写的vc
30 | 31 | -------------------------------------------------------------------------------- /D3Generator/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 | -------------------------------------------------------------------------------- /D3Generator/TestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController : UIViewController 12 | 13 | @property(nonatomic,strong)NSString *titleName; 14 | 15 | @property(nonatomic,strong)NSString *comFrom; 16 | @end 17 | -------------------------------------------------------------------------------- /D3Generator/TestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import "TestViewController.h" 10 | 11 | @interface TestViewController () 12 | 13 | @end 14 | 15 | @implementation TestViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | 22 | UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 300, 100)]; 23 | label.text = [NSString stringWithFormat:@"我是2 我来自:%@",_comFrom]; 24 | [self.view addSubview:label]; 25 | 26 | self.navigationItem.title = _titleName; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /D3Generator/TestViewController1.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController1.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController1 : UIViewController 12 | 13 | @property(nonatomic,strong)NSString *comFrom; 14 | @end 15 | -------------------------------------------------------------------------------- /D3Generator/TestViewController1.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController1.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import "TestViewController1.h" 10 | 11 | @interface TestViewController1 () 12 | @property (weak, nonatomic) IBOutlet UILabel *fromLabel; 13 | 14 | @end 15 | 16 | @implementation TestViewController1 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | _fromLabel.text = [NSString stringWithFormat:@"我是2 我来自:%@",_comFrom]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /D3Generator/TestViewController1.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /D3Generator/TestViewController2.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController2.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController2 : UIViewController 12 | 13 | @property(nonatomic,strong)NSString *comFrom; 14 | @end 15 | -------------------------------------------------------------------------------- /D3Generator/TestViewController2.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController2.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/6. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import "TestViewController2.h" 10 | 11 | @interface TestViewController2 () 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *fromLabel; 14 | @end 15 | 16 | @implementation TestViewController2 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | _fromLabel.text = [NSString stringWithFormat:@"i create by storyboard 我来自:%@",_comFrom]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /D3Generator/WebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.h 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/5. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WebViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /D3Generator/WebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/5. 6 | // Copyright © 2016年 莫振华. All rights reserved. 7 | // 8 | 9 | #import "WebViewController.h" 10 | #import "WebViewJavascriptBridge.h" 11 | #import "D3Generator.h" 12 | #import "NSObject+D3.h" 13 | #import // 导入运行时文件 14 | 15 | @interface WebViewController () 16 | @property(nonatomic,strong)WebViewJavascriptBridge *bridge; 17 | @property (weak, nonatomic) IBOutlet UIWebView *webView; 18 | 19 | @end 20 | 21 | @implementation WebViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.view.backgroundColor = [UIColor whiteColor]; 26 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"]; 27 | NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil]; 28 | NSURL *baseURL = [NSURL fileURLWithPath:htmlPath]; 29 | [_webView loadHTMLString:appHtml baseURL:baseURL]; 30 | [self addRoute:_webView]; 31 | 32 | 33 | // [WebViewController swizzleMethod:@selector(cry) withMethod:@selector(smile) withTarget:self]; 34 | Method oldMethod = class_getInstanceMethod(self.class, @selector(cry)); 35 | Method newMethod = class_getInstanceMethod(self.class, @selector(smile)); 36 | 37 | method_setImplementation(oldMethod, method_getImplementation(newMethod)); 38 | [self cry]; 39 | } 40 | 41 | -(void)smile{ 42 | NSLog(@"smile"); 43 | } 44 | 45 | -(void)cry{ 46 | NSLog(@"cry"); 47 | } 48 | 49 | -(void)addRoute:(UIWebView*)webView{ 50 | _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) { 51 | NSLog(@"ObjC received message from JS: %@", data); 52 | responseCallback(@"报告: IOS收到!!!"); 53 | 54 | [D3Generator createViewControllerWithDictAndPush:data]; 55 | // 或者: 56 | // UIViewController *vc = [D3Generator createViewControllerWithDict:data]; 57 | // [self.navigationController pushViewController:vc animated:YES]; 58 | }]; 59 | } 60 | @end 61 | -------------------------------------------------------------------------------- /D3Generator/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // D3Generator 4 | // 5 | // Created by 莫振华 on 16/2/5. 6 | // Copyright © 2016年 莫振华. 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 莫振华 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ##简介 3 | 根据dict字典生成对象。 适用webview和push推送时,根据后台传回字典实现动态跳转。 4 | ###场景1:从apns推送来的的信息,根据服务端推送过来的数据规则,跳转到对应的控制器。 5 | ###场景2:点击webview中某条链接时,跳转到原生ViewController中继续机型后续操作。 6 | 要实现以上的产品逻辑, 通常都需要前后端约定一些规则实现跳转。 7 | 弊端很明显, 需要开发前就约定很多规则, 并且不一定能覆盖所有逻辑。 8 | 本项目就是为了实现这种逻辑,只要根据后台返回的数据则可实现万能跳转。 9 | 10 | ##使用 11 | 可以直接根据字典规则跳转 12 | '' [D3Generator createViewControllerWithDictAndPush:data]; 13 | 14 | 可以生成控制器自行跳转 15 | '' UIViewController *vc = [D3Generator createViewControllerWithDict:data]; 16 | 17 | data的格式如: 18 | { 19 | 'className':"xxxxVC", 20 | 'name':'D3', 21 | } 22 | 只有className参数是必须的, 这个字段决定了要生成的控制器ViewController 23 | --------------------------------------------------------------------------------