├── .gitignore ├── CTMediator.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── cuibo.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── casa.xcuserdatad │ └── xcschemes │ │ ├── CTMediator.xcscheme │ │ └── xcschememanagement.plist │ └── cuibo.xcuserdatad │ └── xcschemes │ ├── CTMediator.xcscheme │ └── xcschememanagement.plist ├── CTMediator ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── image.imageset │ │ ├── Contents.json │ │ └── image.png │ └── noImage.imageset │ │ ├── Contents.json │ │ └── noImage.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CTMediator │ ├── CTMediator.h │ ├── CTMediator.m │ └── Categories │ │ └── ModuleA │ │ ├── CTMediator+CTMediatorModuleAActions.h │ │ └── CTMediator+CTMediatorModuleAActions.m ├── DemoModule │ ├── Actions │ │ ├── Target_A.h │ │ └── Target_A.m │ ├── DemoModuleADetailViewController.h │ └── DemoModuleADetailViewController.m ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | CTMediator.xcworkspace/ 2 | Podfile.lock 3 | Pods/ 4 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4A5CE4FF1C9531C9006AEDB9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE4FE1C9531C9006AEDB9 /* main.m */; }; 11 | 4A5CE5021C9531C9006AEDB9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */; }; 12 | 4A5CE5051C9531C9006AEDB9 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5041C9531C9006AEDB9 /* ViewController.m */; }; 13 | 4A5CE5081C9531C9006AEDB9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE5061C9531C9006AEDB9 /* Main.storyboard */; }; 14 | 4A5CE50A1C9531C9006AEDB9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */; }; 15 | 4A5CE50D1C9531C9006AEDB9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */; }; 16 | 4A5CE51A1C95322F006AEDB9 /* CTMediator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5191C95322F006AEDB9 /* CTMediator.m */; }; 17 | 4A5CE51D1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE51C1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.m */; }; 18 | 4A5CE5251C953D7D006AEDB9 /* DemoModuleADetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */; }; 19 | 4A5CE52B1C9547B2006AEDB9 /* Target_A.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE52A1C9547B2006AEDB9 /* Target_A.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CTMediator.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 4A5CE4FE1C9531C9006AEDB9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | 4A5CE5001C9531C9006AEDB9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 4A5CE5031C9531C9006AEDB9 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 4A5CE5041C9531C9006AEDB9 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 4A5CE5071C9531C9006AEDB9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 4A5CE50C1C9531C9006AEDB9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 4A5CE50E1C9531C9006AEDB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 4A5CE5181C95322F006AEDB9 /* CTMediator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTMediator.h; sourceTree = ""; }; 34 | 4A5CE5191C95322F006AEDB9 /* CTMediator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CTMediator.m; sourceTree = ""; }; 35 | 4A5CE51B1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CTMediator+CTMediatorModuleAActions.h"; sourceTree = ""; }; 36 | 4A5CE51C1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CTMediator+CTMediatorModuleAActions.m"; sourceTree = ""; }; 37 | 4A5CE5231C953D7D006AEDB9 /* DemoModuleADetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoModuleADetailViewController.h; sourceTree = ""; }; 38 | 4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoModuleADetailViewController.m; sourceTree = ""; }; 39 | 4A5CE5291C9547B2006AEDB9 /* Target_A.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Target_A.h; sourceTree = ""; }; 40 | 4A5CE52A1C9547B2006AEDB9 /* Target_A.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Target_A.m; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 4A5CE4F71C9531C9006AEDB9 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | 4A5CE4F11C9531C9006AEDB9 = { 55 | isa = PBXGroup; 56 | children = ( 57 | 4A5CE4FC1C9531C9006AEDB9 /* CTMediator */, 58 | 4A5CE4FB1C9531C9006AEDB9 /* Products */, 59 | 9449B9483205DCF29E913981 /* Frameworks */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 4A5CE4FB1C9531C9006AEDB9 /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 4A5CE4FC1C9531C9006AEDB9 /* CTMediator */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 4A5CE5141C9531E9006AEDB9 /* CTMediator */, 75 | 4A5CE5211C953D5A006AEDB9 /* DemoModule */, 76 | 4A5CE5001C9531C9006AEDB9 /* AppDelegate.h */, 77 | 4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */, 78 | 4A5CE5031C9531C9006AEDB9 /* ViewController.h */, 79 | 4A5CE5041C9531C9006AEDB9 /* ViewController.m */, 80 | 4A5CE5061C9531C9006AEDB9 /* Main.storyboard */, 81 | 4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */, 82 | 4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */, 83 | 4A5CE50E1C9531C9006AEDB9 /* Info.plist */, 84 | 4A5CE4FD1C9531C9006AEDB9 /* Supporting Files */, 85 | ); 86 | path = CTMediator; 87 | sourceTree = ""; 88 | }; 89 | 4A5CE4FD1C9531C9006AEDB9 /* Supporting Files */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 4A5CE4FE1C9531C9006AEDB9 /* main.m */, 93 | ); 94 | name = "Supporting Files"; 95 | sourceTree = ""; 96 | }; 97 | 4A5CE5141C9531E9006AEDB9 /* CTMediator */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 4A5CE5181C95322F006AEDB9 /* CTMediator.h */, 101 | 4A5CE5191C95322F006AEDB9 /* CTMediator.m */, 102 | 4A5CE5151C95320F006AEDB9 /* Categories */, 103 | ); 104 | path = CTMediator; 105 | sourceTree = ""; 106 | }; 107 | 4A5CE5151C95320F006AEDB9 /* Categories */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 4A5CE5161C95320F006AEDB9 /* ModuleA */, 111 | ); 112 | path = Categories; 113 | sourceTree = ""; 114 | }; 115 | 4A5CE5161C95320F006AEDB9 /* ModuleA */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 4A5CE51B1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.h */, 119 | 4A5CE51C1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.m */, 120 | ); 121 | path = ModuleA; 122 | sourceTree = ""; 123 | }; 124 | 4A5CE5211C953D5A006AEDB9 /* DemoModule */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 4A5CE5221C953D5A006AEDB9 /* Actions */, 128 | 4A5CE5231C953D7D006AEDB9 /* DemoModuleADetailViewController.h */, 129 | 4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */, 130 | ); 131 | path = DemoModule; 132 | sourceTree = ""; 133 | }; 134 | 4A5CE5221C953D5A006AEDB9 /* Actions */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 4A5CE5291C9547B2006AEDB9 /* Target_A.h */, 138 | 4A5CE52A1C9547B2006AEDB9 /* Target_A.m */, 139 | ); 140 | path = Actions; 141 | sourceTree = ""; 142 | }; 143 | 9449B9483205DCF29E913981 /* Frameworks */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | ); 147 | name = Frameworks; 148 | sourceTree = ""; 149 | }; 150 | /* End PBXGroup section */ 151 | 152 | /* Begin PBXNativeTarget section */ 153 | 4A5CE4F91C9531C9006AEDB9 /* CTMediator */ = { 154 | isa = PBXNativeTarget; 155 | buildConfigurationList = 4A5CE5111C9531C9006AEDB9 /* Build configuration list for PBXNativeTarget "CTMediator" */; 156 | buildPhases = ( 157 | 4A5CE4F61C9531C9006AEDB9 /* Sources */, 158 | 4A5CE4F71C9531C9006AEDB9 /* Frameworks */, 159 | 4A5CE4F81C9531C9006AEDB9 /* Resources */, 160 | ); 161 | buildRules = ( 162 | ); 163 | dependencies = ( 164 | ); 165 | name = CTMediator; 166 | productName = CTMediator; 167 | productReference = 4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */; 168 | productType = "com.apple.product-type.application"; 169 | }; 170 | /* End PBXNativeTarget section */ 171 | 172 | /* Begin PBXProject section */ 173 | 4A5CE4F21C9531C9006AEDB9 /* Project object */ = { 174 | isa = PBXProject; 175 | attributes = { 176 | LastUpgradeCheck = 0720; 177 | ORGANIZATIONNAME = casa; 178 | TargetAttributes = { 179 | 4A5CE4F91C9531C9006AEDB9 = { 180 | CreatedOnToolsVersion = 7.2.1; 181 | }; 182 | }; 183 | }; 184 | buildConfigurationList = 4A5CE4F51C9531C9006AEDB9 /* Build configuration list for PBXProject "CTMediator" */; 185 | compatibilityVersion = "Xcode 3.2"; 186 | developmentRegion = English; 187 | hasScannedForEncodings = 0; 188 | knownRegions = ( 189 | en, 190 | Base, 191 | ); 192 | mainGroup = 4A5CE4F11C9531C9006AEDB9; 193 | productRefGroup = 4A5CE4FB1C9531C9006AEDB9 /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 4A5CE4F91C9531C9006AEDB9 /* CTMediator */, 198 | ); 199 | }; 200 | /* End PBXProject section */ 201 | 202 | /* Begin PBXResourcesBuildPhase section */ 203 | 4A5CE4F81C9531C9006AEDB9 /* Resources */ = { 204 | isa = PBXResourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 4A5CE50D1C9531C9006AEDB9 /* LaunchScreen.storyboard in Resources */, 208 | 4A5CE50A1C9531C9006AEDB9 /* Assets.xcassets in Resources */, 209 | 4A5CE5081C9531C9006AEDB9 /* Main.storyboard in Resources */, 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | /* End PBXResourcesBuildPhase section */ 214 | 215 | /* Begin PBXSourcesBuildPhase section */ 216 | 4A5CE4F61C9531C9006AEDB9 /* Sources */ = { 217 | isa = PBXSourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 4A5CE51D1C9538CB006AEDB9 /* CTMediator+CTMediatorModuleAActions.m in Sources */, 221 | 4A5CE5051C9531C9006AEDB9 /* ViewController.m in Sources */, 222 | 4A5CE5021C9531C9006AEDB9 /* AppDelegate.m in Sources */, 223 | 4A5CE4FF1C9531C9006AEDB9 /* main.m in Sources */, 224 | 4A5CE5251C953D7D006AEDB9 /* DemoModuleADetailViewController.m in Sources */, 225 | 4A5CE51A1C95322F006AEDB9 /* CTMediator.m in Sources */, 226 | 4A5CE52B1C9547B2006AEDB9 /* Target_A.m in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | /* End PBXSourcesBuildPhase section */ 231 | 232 | /* Begin PBXVariantGroup section */ 233 | 4A5CE5061C9531C9006AEDB9 /* Main.storyboard */ = { 234 | isa = PBXVariantGroup; 235 | children = ( 236 | 4A5CE5071C9531C9006AEDB9 /* Base */, 237 | ); 238 | name = Main.storyboard; 239 | sourceTree = ""; 240 | }; 241 | 4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */ = { 242 | isa = PBXVariantGroup; 243 | children = ( 244 | 4A5CE50C1C9531C9006AEDB9 /* Base */, 245 | ); 246 | name = LaunchScreen.storyboard; 247 | sourceTree = ""; 248 | }; 249 | /* End PBXVariantGroup section */ 250 | 251 | /* Begin XCBuildConfiguration section */ 252 | 4A5CE50F1C9531C9006AEDB9 /* Debug */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | ALWAYS_SEARCH_USER_PATHS = NO; 256 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 257 | CLANG_CXX_LIBRARY = "libc++"; 258 | CLANG_ENABLE_MODULES = YES; 259 | CLANG_ENABLE_OBJC_ARC = YES; 260 | CLANG_WARN_BOOL_CONVERSION = YES; 261 | CLANG_WARN_CONSTANT_CONVERSION = YES; 262 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 267 | CLANG_WARN_UNREACHABLE_CODE = YES; 268 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 269 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 270 | COPY_PHASE_STRIP = NO; 271 | DEBUG_INFORMATION_FORMAT = dwarf; 272 | ENABLE_STRICT_OBJC_MSGSEND = YES; 273 | ENABLE_TESTABILITY = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu99; 275 | GCC_DYNAMIC_NO_PIC = NO; 276 | GCC_NO_COMMON_BLOCKS = YES; 277 | GCC_OPTIMIZATION_LEVEL = 0; 278 | GCC_PREPROCESSOR_DEFINITIONS = ( 279 | "DEBUG=1", 280 | "$(inherited)", 281 | ); 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 289 | MTL_ENABLE_DEBUG_INFO = YES; 290 | ONLY_ACTIVE_ARCH = YES; 291 | SDKROOT = iphoneos; 292 | TARGETED_DEVICE_FAMILY = "1,2"; 293 | }; 294 | name = Debug; 295 | }; 296 | 4A5CE5101C9531C9006AEDB9 /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ALWAYS_SEARCH_USER_PATHS = NO; 300 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 301 | CLANG_CXX_LIBRARY = "libc++"; 302 | CLANG_ENABLE_MODULES = YES; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_WARN_BOOL_CONVERSION = YES; 305 | CLANG_WARN_CONSTANT_CONVERSION = YES; 306 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 307 | CLANG_WARN_EMPTY_BODY = YES; 308 | CLANG_WARN_ENUM_CONVERSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 311 | CLANG_WARN_UNREACHABLE_CODE = YES; 312 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 313 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 314 | COPY_PHASE_STRIP = NO; 315 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 316 | ENABLE_NS_ASSERTIONS = NO; 317 | ENABLE_STRICT_OBJC_MSGSEND = YES; 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_NO_COMMON_BLOCKS = YES; 320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 322 | GCC_WARN_UNDECLARED_SELECTOR = YES; 323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 324 | GCC_WARN_UNUSED_FUNCTION = YES; 325 | GCC_WARN_UNUSED_VARIABLE = YES; 326 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 327 | MTL_ENABLE_DEBUG_INFO = NO; 328 | SDKROOT = iphoneos; 329 | TARGETED_DEVICE_FAMILY = "1,2"; 330 | VALIDATE_PRODUCT = YES; 331 | }; 332 | name = Release; 333 | }; 334 | 4A5CE5121C9531C9006AEDB9 /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 338 | INFOPLIST_FILE = CTMediator/Info.plist; 339 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 340 | PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediator; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | }; 343 | name = Debug; 344 | }; 345 | 4A5CE5131C9531C9006AEDB9 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 349 | INFOPLIST_FILE = CTMediator/Info.plist; 350 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 351 | PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediator; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | }; 354 | name = Release; 355 | }; 356 | /* End XCBuildConfiguration section */ 357 | 358 | /* Begin XCConfigurationList section */ 359 | 4A5CE4F51C9531C9006AEDB9 /* Build configuration list for PBXProject "CTMediator" */ = { 360 | isa = XCConfigurationList; 361 | buildConfigurations = ( 362 | 4A5CE50F1C9531C9006AEDB9 /* Debug */, 363 | 4A5CE5101C9531C9006AEDB9 /* Release */, 364 | ); 365 | defaultConfigurationIsVisible = 0; 366 | defaultConfigurationName = Release; 367 | }; 368 | 4A5CE5111C9531C9006AEDB9 /* Build configuration list for PBXNativeTarget "CTMediator" */ = { 369 | isa = XCConfigurationList; 370 | buildConfigurations = ( 371 | 4A5CE5121C9531C9006AEDB9 /* Debug */, 372 | 4A5CE5131C9531C9006AEDB9 /* Release */, 373 | ); 374 | defaultConfigurationIsVisible = 0; 375 | defaultConfigurationName = Release; 376 | }; 377 | /* End XCConfigurationList section */ 378 | }; 379 | rootObject = 4A5CE4F21C9531C9006AEDB9 /* Project object */; 380 | } 381 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/project.xcworkspace/xcuserdata/cuibo.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcsoft/ZC_CTMediator/da176eed48f244348e530903eeef487846e9789b/CTMediator.xcodeproj/project.xcworkspace/xcuserdata/cuibo.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/CTMediator.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 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CTMediator.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4A5CE4F91C9531C9006AEDB9 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/xcuserdata/cuibo.xcuserdatad/xcschemes/CTMediator.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 | -------------------------------------------------------------------------------- /CTMediator.xcodeproj/xcuserdata/cuibo.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CTMediator.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4A5CE4F91C9531C9006AEDB9 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CTMediator/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. 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 | -------------------------------------------------------------------------------- /CTMediator/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "CTMediator.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | return YES; 22 | } 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // 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. 27 | } 28 | 29 | - (void)applicationDidEnterBackground:(UIApplication *)application { 30 | // 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. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | - (void)applicationWillEnterForeground:(UIApplication *)application { 35 | // 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. 36 | } 37 | 38 | - (void)applicationDidBecomeActive:(UIApplication *)application { 39 | // 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. 40 | } 41 | 42 | - (void)applicationWillTerminate:(UIApplication *)application { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options 47 | { 48 | return [[[CTMediator sharedInstance] performActionWithUrl:url completion:nil] boolValue]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/image.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcsoft/ZC_CTMediator/da176eed48f244348e530903eeef487846e9789b/CTMediator/Assets.xcassets/image.imageset/image.png -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/noImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "noImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CTMediator/Assets.xcassets/noImage.imageset/noImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcsoft/ZC_CTMediator/da176eed48f244348e530903eeef487846e9789b/CTMediator/Assets.xcassets/noImage.imageset/noImage.png -------------------------------------------------------------------------------- /CTMediator/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 | -------------------------------------------------------------------------------- /CTMediator/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 | -------------------------------------------------------------------------------- /CTMediator/CTMediator/CTMediator.h: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface CTMediator : NSObject 13 | 14 | + (instancetype)sharedInstance; 15 | 16 | // 远程App调用入口 17 | - (id)performActionWithUrl:(NSURL *)url completion:(void(^)(NSDictionary *info))completion; 18 | // 本地组件调用入口 19 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CTMediator/CTMediator/CTMediator.m: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "CTMediator.h" 10 | 11 | @implementation CTMediator 12 | 13 | #pragma mark - public methods 14 | + (instancetype)sharedInstance 15 | { 16 | static CTMediator *mediator; 17 | static dispatch_once_t onceToken; 18 | dispatch_once(&onceToken, ^{ 19 | mediator = [[CTMediator alloc] init]; 20 | }); 21 | return mediator; 22 | } 23 | 24 | /* 25 | scheme://[target]/[action]?[params] 26 | 27 | url sample: 28 | aaa://targetA/actionB?id=1234 29 | */ 30 | 31 | - (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary *))completion 32 | { 33 | #warning todo 修改aaa为你自己app的scheme 34 | if (![url.scheme isEqualToString:@"aaa"]) { 35 | // 这里就是针对远程app调用404的简单处理了,根据不同app的产品经理要求不同,你们可以在这里自己做需要的逻辑 36 | return @(NO); 37 | } 38 | 39 | NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 40 | NSString *urlString = [url query]; 41 | for (NSString *param in [urlString componentsSeparatedByString:@"&"]) { 42 | NSArray *elts = [param componentsSeparatedByString:@"="]; 43 | if([elts count] < 2) continue; 44 | [params setObject:[elts lastObject] forKey:[elts firstObject]]; 45 | } 46 | 47 | // 这里这么写主要是出于安全考虑,防止黑客通过远程方式调用本地模块。这里的做法足以应对绝大多数场景,如果要求更加严苛,也可以做更加复杂的安全逻辑。 48 | NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""]; 49 | if ([actionName hasPrefix:@"native"]) { 50 | return @(NO); 51 | } 52 | 53 | // 这个demo针对URL的路由处理非常简单,就只是取对应的target名字和method名字,但这已经足以应对绝大部份需求。如果需要拓展,可以在这个方法调用之前加入完整的路由逻辑 54 | id result = [self performTarget:url.host action:actionName params:params]; 55 | if (completion) { 56 | if (result) { 57 | completion(@{@"result":result}); 58 | } else { 59 | completion(nil); 60 | } 61 | } 62 | return result; 63 | } 64 | 65 | - (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params 66 | { 67 | 68 | NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName]; 69 | NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName]; 70 | 71 | Class targetClass = NSClassFromString(targetClassString); 72 | id target = [[targetClass alloc] init]; 73 | SEL action = NSSelectorFromString(actionString); 74 | 75 | if (target == nil) { 76 | // 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以响应的target,就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的 77 | return nil; 78 | } 79 | 80 | if ([target respondsToSelector:action]) { 81 | #pragma clang diagnostic push 82 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 83 | return [target performSelector:action withObject:params]; 84 | #pragma clang diagnostic pop 85 | } else { 86 | // 这里是处理无响应请求的地方,如果无响应,则尝试调用对应target的notFound方法统一处理 87 | SEL action = NSSelectorFromString(@"notFound:"); 88 | if ([target respondsToSelector:action]) { 89 | #pragma clang diagnostic push 90 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 91 | //3 根据CTMediator+CTMediatorModuleAActions.m传过来的目标和参数发起实际调用。这个调用关系是在运行时完成的。所以此处并不需要在代码上依赖被调用者,如果被调用者不存在,也可以在运行时进行处理(处理方法参见上面几行代码)。 92 | //7: CTMediator.m返回步骤6中得到的实例到CTMediator+CTMediatorModuleAActions.m(发起时是步骤2) 93 | return [target performSelector:action withObject:params]; 94 | #pragma clang diagnostic pop 95 | } else { 96 | // 这里也是处理无响应请求的地方,在notFound都没有的时候,这个demo是直接return了。实际开发过程中,可以用前面提到的固定的target顶上的。 97 | return nil; 98 | } 99 | } 100 | } 101 | 102 | @end -------------------------------------------------------------------------------- /CTMediator/CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.h: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator+CTMediatorModuleAActions.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "CTMediator.h" 10 | #import 11 | 12 | @interface CTMediator (CTMediatorModuleAActions) 13 | 14 | - (UIViewController *)CTMediator_viewControllerForDetail; 15 | - (void)CTMediator_showAlertWithMessage:(NSString *)message cancelAction:(void(^)(NSDictionary *info))cancelAction confirmAction:(void(^)(NSDictionary *info))confirmAction; 16 | - (void)CTMediator_presentImage:(UIImage *)image; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /CTMediator/CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.m: -------------------------------------------------------------------------------- 1 | // 2 | // CTMediator+CTMediatorModuleAActions.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "CTMediator+CTMediatorModuleAActions.h" 10 | 11 | NSString * const kCTMediatorTargetA = @"A"; 12 | 13 | NSString * const kCTMediatorActionNativFetchDetailViewController = @"nativeFetchDetailViewController"; 14 | NSString * const kCTMediatorActionNativePresentImage = @"nativePresentImage"; 15 | NSString * const kCTMediatorActionNativeNoImage = @"nativeNoImage"; 16 | NSString * const kCTMediatorActionShowAlert = @"showAlert"; 17 | 18 | @implementation CTMediator (CTMediatorModuleAActions) 19 | 20 | - (UIViewController *)CTMediator_viewControllerForDetail 21 | { 22 | //2:通过定义好的参数调用CTMediator,由于CTMediator+CTMediatorModuleAActions是CTMediator的扩展,所以可以直接使用self来调用CTMediator的实现 23 | UIViewController *viewController = [self performTarget:kCTMediatorTargetA 24 | action:kCTMediatorActionNativFetchDetailViewController 25 | params:@{@"key":@"value"}]; 26 | if ([viewController isKindOfClass:[UIViewController class]]) { 27 | // view controller 交付出去之后,可以由外界选择是push还是present 28 | //8: CTMediator+CTMediatorModuleAActions.m会将步骤7返回的实例当作UIViewController处理,接下来会在运行时判断这个实例的类型是不是UIViewController(是不是UIViewController的子类)。然后将得到的UIViewController交给调用者ViewController.m(由ViewController.m负责以何种方式进行展示)。 29 | return viewController; 30 | } else { 31 | // 这里处理异常场景,具体如何处理取决于产品 32 | return [[UIViewController alloc] init]; 33 | } 34 | } 35 | 36 | - (void)CTMediator_presentImage:(UIImage *)image 37 | { 38 | if (image) { 39 | [self performTarget:kCTMediatorTargetA 40 | action:kCTMediatorActionNativePresentImage 41 | params:@{@"image":image}]; 42 | } else { 43 | // 这里处理image为nil的场景,如何处理取决于产品 44 | [self performTarget:kCTMediatorTargetA 45 | action:kCTMediatorActionNativeNoImage 46 | params:@{@"image":[UIImage imageNamed:@"noImage"]}]; 47 | } 48 | } 49 | 50 | - (void)CTMediator_showAlertWithMessage:(NSString *)message cancelAction:(void(^)(NSDictionary *info))cancelAction confirmAction:(void(^)(NSDictionary *info))confirmAction 51 | { 52 | NSMutableDictionary *paramsToSend = [[NSMutableDictionary alloc] init]; 53 | if (message) { 54 | paramsToSend[@"message"] = message; 55 | } 56 | if (cancelAction) { 57 | paramsToSend[@"cancelAction"] = cancelAction; 58 | } 59 | if (confirmAction) { 60 | paramsToSend[@"confirmAction"] = confirmAction; 61 | } 62 | [self performTarget:kCTMediatorTargetA 63 | action:kCTMediatorActionShowAlert 64 | params:paramsToSend]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /CTMediator/DemoModule/Actions/Target_A.h: -------------------------------------------------------------------------------- 1 | // 2 | // Target_A.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface Target_A : NSObject 14 | 15 | - (UIViewController *)Action_nativeFetchDetailViewController:(NSDictionary *)params; 16 | - (id)Action_nativePresentImage:(NSDictionary *)params; 17 | - (id)Action_showAlert:(NSDictionary *)params; 18 | 19 | // 容错 20 | - (id)Action_nativeNoImage:(NSDictionary *)params; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /CTMediator/DemoModule/Actions/Target_A.m: -------------------------------------------------------------------------------- 1 | // 2 | // Target_A.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "Target_A.h" 10 | #import "DemoModuleADetailViewController.h" 11 | 12 | typedef void (^CTUrlRouterCallbackBlock)(NSDictionary *info); 13 | 14 | @implementation Target_A 15 | 16 | - (UIViewController *)Action_nativeFetchDetailViewController:(NSDictionary *)params 17 | { 18 | // 因为action是从属于ModuleA的,所以action直接可以使用ModuleA里的所有声明 19 | //4/5: 创建一个DemoModuleADetailViewController类型的实例(这个实例是Target_A通过DemoModuleADetailViewController类的alloc/init创建的)。 20 | DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init]; 21 | viewController.valueLabel.text = params[@"key"]; 22 | //6: Target_A返回创建的实例到CTMediator.m(发起时是通过runtime,步骤3),返回后CTMediator.m并不知道这个实例的具体类型,也不会对这个类进行任何解析操作,所以CTMediator.m跟返回的实例之间是没有任何引用关系的。 23 | return viewController; 24 | } 25 | 26 | - (id)Action_nativePresentImage:(NSDictionary *)params 27 | { 28 | DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init]; 29 | viewController.valueLabel.text = @"this is image"; 30 | viewController.imageView.image = params[@"image"]; 31 | [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil]; 32 | return nil; 33 | } 34 | 35 | - (id)Action_showAlert:(NSDictionary *)params 36 | { 37 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { 38 | CTUrlRouterCallbackBlock callback = params[@"cancelAction"]; 39 | if (callback) { 40 | callback(@{@"alertAction":action}); 41 | } 42 | }]; 43 | 44 | UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"confirm" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 45 | CTUrlRouterCallbackBlock callback = params[@"confirmAction"]; 46 | if (callback) { 47 | callback(@{@"alertAction":action}); 48 | } 49 | }]; 50 | 51 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"alert from Module A" message:params[@"message"] preferredStyle:UIAlertControllerStyleAlert]; 52 | [alertController addAction:cancelAction]; 53 | [alertController addAction:confirmAction]; 54 | [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil]; 55 | return nil; 56 | } 57 | 58 | - (id)Action_nativeNoImage:(NSDictionary *)params 59 | { 60 | DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init]; 61 | viewController.valueLabel.text = @"no image"; 62 | viewController.imageView.image = [UIImage imageNamed:@"noImage"]; 63 | [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil]; 64 | 65 | return nil; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /CTMediator/DemoModule/DemoModuleADetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModuleADetailViewController.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoModuleADetailViewController : UIViewController 12 | 13 | @property (nonatomic, strong, readonly) UILabel *valueLabel; 14 | @property (nonatomic, strong, readonly) UIImageView *imageView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CTMediator/DemoModule/DemoModuleADetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModuleADetailViewController.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "DemoModuleADetailViewController.h" 10 | 11 | @interface DemoModuleADetailViewController () 12 | 13 | @property (nonatomic, strong, readwrite) UILabel *valueLabel; 14 | @property (nonatomic, strong, readwrite) UIImageView *imageView; 15 | 16 | @property (nonatomic, strong) UIButton *returnButton; 17 | 18 | @end 19 | 20 | @implementation DemoModuleADetailViewController 21 | 22 | #pragma mark - life cycle 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.view.backgroundColor = [UIColor grayColor]; 26 | 27 | [self.view addSubview:self.valueLabel]; 28 | [self.view addSubview:self.imageView]; 29 | [self.view addSubview:self.returnButton]; 30 | } 31 | 32 | - (void)viewWillAppear:(BOOL)animated 33 | { 34 | [super viewWillAppear:animated]; 35 | 36 | [self.valueLabel sizeToFit]; 37 | self.valueLabel.frame = (CGRect){(self.view.bounds.size.width-self.valueLabel.frame.size.width)/2,70, self.valueLabel.frame.size}; 38 | 39 | self.imageView.frame = (CGRect){(self.view.bounds.size.width-100)/2,120, 100,100}; 40 | 41 | self.returnButton.frame = (CGRect){(self.view.bounds.size.width-100)/2,self.view.bounds.size.height-120, 100,100}; 42 | } 43 | 44 | #pragma mark - event response 45 | - (void)didTappedReturnButton:(UIButton *)button 46 | { 47 | if (self.navigationController == nil) { 48 | [self dismissViewControllerAnimated:YES completion:nil]; 49 | } else { 50 | [self.navigationController popViewControllerAnimated:YES]; 51 | } 52 | } 53 | 54 | #pragma mark - getters and setters 55 | - (UILabel *)valueLabel 56 | { 57 | if (_valueLabel == nil) { 58 | _valueLabel = [[UILabel alloc] init]; 59 | _valueLabel.font = [UIFont systemFontOfSize:30]; 60 | _valueLabel.textColor = [UIColor blackColor]; 61 | } 62 | return _valueLabel; 63 | } 64 | 65 | - (UIImageView *)imageView 66 | { 67 | if (_imageView == nil) { 68 | _imageView = [[UIImageView alloc] init]; 69 | _imageView.contentMode = UIViewContentModeScaleAspectFit; 70 | } 71 | return _imageView; 72 | } 73 | 74 | - (UIButton *)returnButton 75 | { 76 | if (_returnButton == nil) { 77 | _returnButton = [UIButton buttonWithType:UIButtonTypeCustom]; 78 | [_returnButton addTarget:self action:@selector(didTappedReturnButton:) forControlEvents:UIControlEventTouchUpInside]; 79 | [_returnButton setTitle:@"return" forState:UIControlStateNormal]; 80 | [_returnButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 81 | } 82 | return _returnButton; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /CTMediator/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 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CTMediator/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CTMediator/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "CTMediator+CTMediatorModuleAActions.h" 11 | 12 | NSString * const kCellIdentifier = @"kCellIdentifier"; 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic, strong) UITableView *tableView; 17 | @property (nonatomic, strong) NSArray *dataSource; 18 | 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | #pragma mark - life cycle 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | 27 | [self.view addSubview:self.tableView]; 28 | } 29 | 30 | - (void)viewWillAppear:(BOOL)animated 31 | { 32 | [super viewWillAppear:animated]; 33 | 34 | self.tableView.frame = self.view.bounds; 35 | } 36 | 37 | #pragma mark - UITableViewDataSource 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 39 | { 40 | return self.dataSource.count; 41 | } 42 | 43 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 44 | { 45 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier]; 46 | cell.textLabel.text = self.dataSource[indexPath.row]; 47 | return cell; 48 | } 49 | 50 | #pragma mark - UITableViewDelegate 51 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 52 | { 53 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 54 | 55 | if (indexPath.row == 0) { 56 | //1: ViewController.m发起调用请求给CTMediator(CTMediator+CTMediatorModuleAActions.m) 57 | UIViewController *viewController = [[CTMediator sharedInstance] CTMediator_viewControllerForDetail]; 58 | 59 | // 获得view controller之后,在这种场景下,到底push还是present,其实是要由使用者决定的,mediator只要给出view controller的实例就好了 60 | [self presentViewController:viewController animated:YES completion:nil]; 61 | } 62 | 63 | if (indexPath.row == 1) { 64 | UIViewController *viewController = [[CTMediator sharedInstance] CTMediator_viewControllerForDetail]; 65 | [self.navigationController pushViewController:viewController animated:YES]; 66 | } 67 | 68 | if (indexPath.row == 2) { 69 | // 这种场景下,很明显是需要被present的,所以不必返回实例,mediator直接present了 70 | [[CTMediator sharedInstance] CTMediator_presentImage:[UIImage imageNamed:@"image"]]; 71 | } 72 | 73 | if (indexPath.row == 3) { 74 | // 这种场景下,参数有问题,因此需要在流程中做好处理 75 | [[CTMediator sharedInstance] CTMediator_presentImage:nil]; 76 | } 77 | 78 | if (indexPath.row == 4) { 79 | [[CTMediator sharedInstance] CTMediator_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) { 80 | // 做你想做的事 81 | NSLog(@"%@", info); 82 | }]; 83 | } 84 | } 85 | 86 | #pragma mark - getters and setters 87 | 88 | - (UITableView *)tableView 89 | { 90 | if (_tableView == nil) { 91 | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 92 | _tableView.delegate = self; 93 | _tableView.dataSource = self; 94 | 95 | [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kCellIdentifier]; 96 | } 97 | return _tableView; 98 | } 99 | 100 | - (NSArray *)dataSource 101 | { 102 | if (_dataSource == nil) { 103 | _dataSource = @[@"present detail view controller", @"push detail view controller", @"present image", @"present image when error", @"show alert"]; 104 | } 105 | return _dataSource; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /CTMediator/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CTMediator 4 | // 5 | // Created by casa on 16/3/13. 6 | // Copyright © 2016年 casa. 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 | ZC_CTMediator 2 | ========== 3 | 4 | . 5 | 6 | [ios业务模块间互相跳转的解耦方案](http://blog.csdn.net/cuibo1123/article/details/51017376) 7 | 8 | 这是CTMediator的整理版本,去掉了CocoPods依赖,增加了一些注释。*[原始版本] (http://casatwy.com/iOS-Modulization.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io) 9 | 10 | --------------------------------------------------------------------------------