Repository: casatwy/CTMediator
Branch: master
Commit: 942e9d8bf43b
Files: 37
Total size: 82.6 KB
Directory structure:
gitextract_58u0q7qj/
├── .gitignore
├── .swift-version
├── CTMediator/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets/
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── image.imageset/
│ │ │ └── Contents.json
│ │ └── noImage.imageset/
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── CTMediator/
│ │ ├── CTMediator+HandyTools.h
│ │ ├── CTMediator+HandyTools.m
│ │ ├── 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
│ ├── TableViewController/
│ │ ├── TableViewController.h
│ │ └── TableViewController.m
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── CTMediator.podspec
├── CTMediator.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcuserdata/
│ └── casa.xcuserdatad/
│ └── xcschemes/
│ ├── CTMediator.xcscheme
│ └── xcschememanagement.plist
├── CTMediatorUITests/
│ ├── CTMediatorUITests.m
│ └── Info.plist
├── FILE_LICENSE
├── Podfile
├── readme.md
└── upload.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
CTMediator.xcworkspace/
Podfile.lock
Pods/
CTMediator.xcodeproj/project.xcworkspace/xcuserdata/
.DS_Store
*.swp
================================================
FILE: .swift-version
================================================
3.0
================================================
FILE: CTMediator/AppDelegate.h
================================================
//
// AppDelegate.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: CTMediator/AppDelegate.m
================================================
//
// AppDelegate.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "AppDelegate.h"
#import "CTMediator.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
// 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.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
return [[[CTMediator sharedInstance] performActionWithUrl:url completion:nil] boolValue];
}
@end
================================================
FILE: CTMediator/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: CTMediator/Assets.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: CTMediator/Assets.xcassets/image.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "image.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: CTMediator/Assets.xcassets/noImage.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "noImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: CTMediator/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
================================================
FILE: CTMediator/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="qDF-Gu-nhm">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="0wq-Yx-mQd"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="728" y="764"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="qSN-kV-SwL">
<objects>
<navigationController id="qDF-Gu-nhm" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="3UI-Ny-RPg">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="ujh-KU-esR"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="HIf-Wd-uPB" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="32" y="764"/>
</scene>
</scenes>
</document>
================================================
FILE: CTMediator/CTMediator/CTMediator+HandyTools.h
================================================
//
// CTMediator+HandyTools.h
// CTMediator
//
// Created by casa on 2020/3/10.
// Copyright © 2020 casa. All rights reserved.
//
#if TARGET_OS_IOS
#import "CTMediator.h"
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface CTMediator (HandyTools)
- (UIViewController * _Nullable)topViewController NS_EXTENSION_UNAVAILABLE_IOS("not available on iOS (App Extension)");
- (UIWindow * _Nullable)keyWindow NS_EXTENSION_UNAVAILABLE_IOS("not available on iOS (App Extension)");
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated NS_EXTENSION_UNAVAILABLE_IOS("not available on iOS (App Extension)");
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)animated completion:(void (^ _Nullable )(void))completion NS_EXTENSION_UNAVAILABLE_IOS("not available on iOS (App Extension)");
@end
NS_ASSUME_NONNULL_END
#endif
================================================
FILE: CTMediator/CTMediator/CTMediator+HandyTools.m
================================================
//
// CTMediator+HandyTools.m
// CTMediator
//
// Created by casa on 2020/3/10.
// Copyright © 2020 casa. All rights reserved.
//
#if TARGET_OS_IOS
#import "CTMediator+HandyTools.h"
@implementation CTMediator (HandyTools)
- (UIWindow *)keyWindow {
if (@available(iOS 13, *)) {
NSArray<UIWindow *> *windows = [[UIApplication sharedApplication] windows];
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
return window;
}
}
}else {
return [UIApplication sharedApplication].keyWindow;
}
return nil;
}
- (UIViewController *)topViewController
{
UIViewController *topController = [self keyWindow].rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UINavigationController *navigationController = (UINavigationController *)[self topViewController];
if ([navigationController isKindOfClass:[UINavigationController class]] == NO) {
if ([navigationController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabbarController = (UITabBarController *)navigationController;
navigationController = tabbarController.selectedViewController;
if ([navigationController isKindOfClass:[UINavigationController class]] == NO) {
navigationController = tabbarController.selectedViewController.navigationController;
}
} else {
navigationController = navigationController.navigationController;
}
}
if ([navigationController isKindOfClass:[UINavigationController class]]) {
[navigationController pushViewController:viewController animated:animated];
}
}
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)animated completion:(void (^ _Nullable)(void))completion
{
UIViewController *viewController = [self topViewController];
if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)viewController;
viewController = navigationController.topViewController;
}
if ([viewController isKindOfClass:[UIAlertController class]]) {
UIViewController *viewControllerToUse = viewController.presentingViewController;
[viewController dismissViewControllerAnimated:false completion:nil];
viewController = viewControllerToUse;
}
if (viewController) {
[viewController presentViewController:viewControllerToPresent animated:animated completion:completion];
}
}
@end
#endif
================================================
FILE: CTMediator/CTMediator/CTMediator.h
================================================
//
// CTMediator.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * _Nonnull const kCTMediatorParamsKeySwiftTargetModuleName;
@interface CTMediator : NSObject
+ (instancetype _Nonnull)sharedInstance;
// 远程App调用入口
- (id _Nullable)performActionWithUrl:(NSURL * _Nullable)url completion:(void(^_Nullable)(NSDictionary * _Nullable info))completion;
// 本地组件调用入口
- (id _Nullable )performTarget:(NSString * _Nullable)targetName action:(NSString * _Nullable)actionName params:(NSDictionary * _Nullable)params shouldCacheTarget:(BOOL)shouldCacheTarget;
- (void)releaseCachedTargetWithFullTargetName:(NSString * _Nullable)fullTargetName;
// 检查 是否有引源码
- (BOOL)check:(NSString * _Nullable)targetName moduleName:(NSString * _Nullable)moduleName;
@end
// 简化调用单例的函数
CTMediator* _Nonnull CT(void);
================================================
FILE: CTMediator/CTMediator/CTMediator.m
================================================
//
// CTMediator.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "CTMediator.h"
#import <objc/runtime.h>
#import <CoreGraphics/CoreGraphics.h>
NSString * const kCTMediatorParamsKeySwiftTargetModuleName = @"kCTMediatorParamsKeySwiftTargetModuleName";
@interface CTMediator ()
@property (nonatomic, strong) NSMutableDictionary *cachedTarget;
@end
@implementation CTMediator
#pragma mark - public methods
+ (instancetype)sharedInstance
{
static CTMediator *mediator;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mediator = [[CTMediator alloc] init];
[mediator cachedTarget]; // 同时把cachedTarget初始化,避免多线程重复初始化
});
return mediator;
}
/*
scheme://[target]/[action]?[params]
url sample:
aaa://targetA/actionB?id=1234
*/
- (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary *))completion
{
if (url == nil||![url isKindOfClass:[NSURL class]]) {
return nil;
}
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url.absoluteString];
// 遍历所有参数
[urlComponents.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.value&&obj.name) {
[params setObject:obj.value forKey:obj.name];
}
}];
// 这里这么写主要是出于安全考虑,防止黑客通过远程方式调用本地模块。这里的做法足以应对绝大多数场景,如果要求更加严苛,也可以做更加复杂的安全逻辑。
NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""];
if ([actionName hasPrefix:@"native"]) {
return @(NO);
}
// 这个demo针对URL的路由处理非常简单,就只是取对应的target名字和method名字,但这已经足以应对绝大部份需求。如果需要拓展,可以在这个方法调用之前加入完整的路由逻辑
id result = [self performTarget:url.host action:actionName params:params shouldCacheTarget:NO];
if (completion) {
if (result) {
completion(@{@"result":result});
} else {
completion(nil);
}
}
return result;
}
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{
if (targetName == nil || actionName == nil) {
return nil;
}
NSString *swiftModuleName = params[kCTMediatorParamsKeySwiftTargetModuleName];
// generate target
NSString *targetClassString = nil;
if (swiftModuleName.length > 0) {
targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModuleName, targetName];
} else {
targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
}
NSObject *target = [self safeFetchCachedTarget:targetClassString];
if (target == nil) {
Class targetClass = NSClassFromString(targetClassString);
target = [[targetClass alloc] init];
}
// generate action
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
SEL action = NSSelectorFromString(actionString);
if (target == nil) {
// 这里是处理无响应请求的地方之一,这个demo做得比较简单,如果没有可以响应的target,就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上,然后处理这种请求的
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
return nil;
}
if (shouldCacheTarget) {
[self safeSetCachedTarget:target key:targetClassString];
}
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 这里是处理无响应请求的地方,如果无响应,则尝试调用对应target的notFound方法统一处理
SEL action = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 这里也是处理无响应请求的地方,在notFound都没有的时候,这个demo是直接return了。实际开发过程中,可以用前面提到的固定的target顶上的。
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
@synchronized (self) {
[self.cachedTarget removeObjectForKey:targetClassString];
}
return nil;
}
}
}
- (void)releaseCachedTargetWithFullTargetName:(NSString *)fullTargetName
{
/*
fullTargetName在oc环境下,就是Target_XXXX。要带上Target_前缀。在swift环境下,就是XXXModule.Target_YYY。不光要带上Target_前缀,还要带上模块名。
*/
if (fullTargetName == nil) {
return;
}
@synchronized (self) {
[self.cachedTarget removeObjectForKey:fullTargetName];
}
}
- (BOOL)check:(NSString * _Nullable)targetName moduleName:(NSString * _Nullable)moduleName{
if (moduleName.length > 0) {
return NSClassFromString([NSString stringWithFormat:@"%@.Target_%@", moduleName, targetName]) != nil;
} else {
return NSClassFromString([NSString stringWithFormat:@"Target_%@", targetName]) != nil;
}
}
#pragma mark - private methods
- (void)NoTargetActionResponseWithTargetString:(NSString *)targetString selectorString:(NSString *)selectorString originParams:(NSDictionary *)originParams
{
SEL action = NSSelectorFromString(@"Action_response:");
NSObject *target = [[NSClassFromString(@"Target_NoTargetAction") alloc] init];
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
params[@"originParams"] = originParams;
params[@"targetString"] = targetString;
params[@"selectorString"] = selectorString;
[self safePerformAction:action target:target params:params];
}
- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params
{
NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
if(methodSig == nil) {
return nil;
}
const char* retType = [methodSig methodReturnType];
if (strcmp(retType, @encode(void)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
return nil;
}
if (strcmp(retType, @encode(NSInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(BOOL)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
BOOL result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(CGFloat)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
CGFloat result = 0;
[invocation getReturnValue:&result];
return @(result);
}
if (strcmp(retType, @encode(NSUInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSUInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
}
#pragma mark - getters and setters
- (NSMutableDictionary *)cachedTarget
{
if (_cachedTarget == nil) {
_cachedTarget = [[NSMutableDictionary alloc] init];
}
return _cachedTarget;
}
- (NSObject *)safeFetchCachedTarget:(NSString *)key {
@synchronized (self) {
return self.cachedTarget[key];
}
}
- (void)safeSetCachedTarget:(NSObject *)target key:(NSString *)key {
@synchronized (self) {
self.cachedTarget[key] = target;
}
}
@end
CTMediator* _Nonnull CT(void){
return [CTMediator sharedInstance];
};
================================================
FILE: CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.h
================================================
//
// CTMediator+CTMediatorModuleAActions.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "CTMediator.h"
#import <UIKit/UIKit.h>
@interface CTMediator (CTMediatorModuleAActions)
- (UIViewController *)CTMediator_viewControllerForDetail;
- (void)CTMediator_showAlertWithMessage:(NSString *)message cancelAction:(void(^)(NSDictionary *info))cancelAction confirmAction:(void(^)(NSDictionary *info))confirmAction;
- (void)CTMediator_presentImage:(UIImage *)image;
- (UITableViewCell *)CTMediator_tableViewCellWithIdentifier:(NSString *)identifier tableView:(UITableView *)tableView;
- (void)CTMediator_configTableViewCell:(UITableViewCell *)cell withTitle:(NSString *)title atIndexPath:(NSIndexPath *)indexPath;
- (void)CTMediator_cleanTableViewCellTarget;
@end
================================================
FILE: CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.m
================================================
//
// CTMediator+CTMediatorModuleAActions.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "CTMediator+CTMediatorModuleAActions.h"
NSString * const kCTMediatorTargetA = @"A";
NSString * const kCTMediatorActionNativeFetchDetailViewController = @"nativeFetchDetailViewController";
NSString * const kCTMediatorActionNativePresentImage = @"nativePresentImage";
NSString * const kCTMediatorActionNativeNoImage = @"nativeNoImage";
NSString * const kCTMediatorActionShowAlert = @"showAlert";
NSString * const kCTMediatorActionCell = @"cell";
NSString * const kCTMediatorActionConfigCell = @"configCell";
@implementation CTMediator (CTMediatorModuleAActions)
- (UIViewController *)CTMediator_viewControllerForDetail
{
UIViewController *viewController = [self performTarget:kCTMediatorTargetA
action:kCTMediatorActionNativeFetchDetailViewController
params:@{@"key":@"value"}
shouldCacheTarget:NO
];
if ([viewController isKindOfClass:[UIViewController class]]) {
// view controller 交付出去之后,可以由外界选择是push还是present
return viewController;
} else {
// 这里处理异常场景,具体如何处理取决于产品
return [[UIViewController alloc] init];
}
}
- (void)CTMediator_presentImage:(UIImage *)image
{
if (image) {
[self performTarget:kCTMediatorTargetA
action:kCTMediatorActionNativePresentImage
params:@{@"image":image}
shouldCacheTarget:NO];
} else {
// 这里处理image为nil的场景,如何处理取决于产品
[self performTarget:kCTMediatorTargetA
action:kCTMediatorActionNativeNoImage
params:@{@"image":[UIImage imageNamed:@"noImage"]}
shouldCacheTarget:NO];
}
}
- (void)CTMediator_showAlertWithMessage:(NSString *)message cancelAction:(void(^)(NSDictionary *info))cancelAction confirmAction:(void(^)(NSDictionary *info))confirmAction
{
NSMutableDictionary *paramsToSend = [[NSMutableDictionary alloc] init];
if (message) {
paramsToSend[@"message"] = message;
}
if (cancelAction) {
paramsToSend[@"cancelAction"] = cancelAction;
}
if (confirmAction) {
paramsToSend[@"confirmAction"] = confirmAction;
}
[self performTarget:kCTMediatorTargetA
action:kCTMediatorActionShowAlert
params:paramsToSend
shouldCacheTarget:NO];
}
- (UITableViewCell *)CTMediator_tableViewCellWithIdentifier:(NSString *)identifier tableView:(UITableView *)tableView
{
return [self performTarget:kCTMediatorTargetA
action:kCTMediatorActionCell
params:@{
@"identifier":identifier,
@"tableView":tableView
}
shouldCacheTarget:YES];
}
- (void)CTMediator_configTableViewCell:(UITableViewCell *)cell withTitle:(NSString *)title atIndexPath:(NSIndexPath *)indexPath
{
[self performTarget:kCTMediatorTargetA
action:kCTMediatorActionConfigCell
params:@{
@"cell":cell,
@"title":title,
@"indexPath":indexPath
}
shouldCacheTarget:YES];
}
- (void)CTMediator_cleanTableViewCellTarget
{
NSString *fullTargetName = [NSString stringWithFormat:@"Target_%@", kCTMediatorTargetA];
[self releaseCachedTargetWithFullTargetName:fullTargetName];
}
@end
================================================
FILE: CTMediator/DemoModule/Actions/Target_A.h
================================================
//
// Target_A.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Target_A : NSObject
- (UIViewController *)Action_nativeFetchDetailViewController:(NSDictionary *)params;
- (id)Action_nativePresentImage:(NSDictionary *)params;
- (id)Action_showAlert:(NSDictionary *)params;
// 容错
- (id)Action_nativeNoImage:(NSDictionary *)params;
@end
================================================
FILE: CTMediator/DemoModule/Actions/Target_A.m
================================================
//
// Target_A.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "Target_A.h"
#import "DemoModuleADetailViewController.h"
typedef void (^CTUrlRouterCallbackBlock)(NSDictionary *info);
@implementation Target_A
- (UIViewController *)Action_nativeFetchDetailViewController:(NSDictionary *)params
{
// 因为action是从属于ModuleA的,所以action直接可以使用ModuleA里的所有声明
DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
viewController.valueLabel.text = params[@"key"];
return viewController;
}
- (id)Action_nativePresentImage:(NSDictionary *)params
{
DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
viewController.valueLabel.text = @"this is image";
viewController.imageView.image = params[@"image"];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
return nil;
}
- (id)Action_showAlert:(NSDictionary *)params
{
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
CTUrlRouterCallbackBlock callback = params[@"cancelAction"];
if (callback) {
callback(@{@"alertAction":action});
}
}];
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"confirm" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
CTUrlRouterCallbackBlock callback = params[@"confirmAction"];
if (callback) {
callback(@{@"alertAction":action});
}
}];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"alert from Module A" message:params[@"message"] preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:cancelAction];
[alertController addAction:confirmAction];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
return nil;
}
- (id)Action_nativeNoImage:(NSDictionary *)params
{
DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
viewController.valueLabel.text = @"no image";
viewController.imageView.image = [UIImage imageNamed:@"noImage"];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
return nil;
}
- (UITableViewCell *)Action_cell:(NSDictionary *)params
{
UITableView *tableView = params[@"tableView"];
NSString *identifier = params[@"identifier"];
// 这里的TableViewCell的类型可以是自定义的,我这边偷懒就不自定义了。
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
return cell;
}
- (id)Action_configCell:(NSDictionary *)params
{
NSString *title = params[@"title"];
NSIndexPath *indexPath = params[@"indexPath"];
UITableViewCell *cell = params[@"cell"];
// 这里的TableViewCell的类型可以是自定义的,我这边偷懒就不自定义了。
cell.textLabel.text = [NSString stringWithFormat:@"%@,%ld", title, (long)indexPath.row];
// if ([cell isKindOfClass:[XXXXXCell class]]) {
// 正常情况下在这里做特定cell的赋值,上面就简单写了
// }
return nil;
}
@end
================================================
FILE: CTMediator/DemoModule/DemoModuleADetailViewController.h
================================================
//
// DemoModuleADetailViewController.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface DemoModuleADetailViewController : UIViewController
@property (nonatomic, strong, readonly) UILabel *valueLabel;
@property (nonatomic, strong, readonly) UIImageView *imageView;
@end
================================================
FILE: CTMediator/DemoModule/DemoModuleADetailViewController.m
================================================
//
// DemoModuleADetailViewController.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "DemoModuleADetailViewController.h"
#import <HandyFrame/UIView+LayoutMethods.h>
@interface DemoModuleADetailViewController ()
@property (nonatomic, strong, readwrite) UILabel *valueLabel;
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@property (nonatomic, strong) UIButton *returnButton;
@end
@implementation DemoModuleADetailViewController
#pragma mark - life cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
[self.view addSubview:self.valueLabel];
[self.view addSubview:self.imageView];
[self.view addSubview:self.returnButton];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self.valueLabel sizeToFit];
[self.valueLabel topInContainer:70 shouldResize:NO];
[self.valueLabel centerXEqualToView:self.view];
self.imageView.ct_size = CGSizeMake(100, 100);
[self.imageView centerEqualToView:self.view];
self.returnButton.ct_size = CGSizeMake(100, 100);
[self.returnButton bottomInContainer:0 shouldResize:NO];
[self.returnButton centerXEqualToView:self.view];
}
#pragma mark - event response
- (void)didTappedReturnButton:(UIButton *)button
{
if (self.navigationController == nil) {
[self dismissViewControllerAnimated:YES completion:nil];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark - getters and setters
- (UILabel *)valueLabel
{
if (_valueLabel == nil) {
_valueLabel = [[UILabel alloc] init];
_valueLabel.font = [UIFont systemFontOfSize:30];
_valueLabel.textColor = [UIColor blackColor];
}
return _valueLabel;
}
- (UIImageView *)imageView
{
if (_imageView == nil) {
_imageView = [[UIImageView alloc] init];
_imageView.contentMode = UIViewContentModeScaleAspectFit;
}
return _imageView;
}
- (UIButton *)returnButton
{
if (_returnButton == nil) {
_returnButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_returnButton addTarget:self action:@selector(didTappedReturnButton:) forControlEvents:UIControlEventTouchUpInside];
[_returnButton setTitle:@"return" forState:UIControlStateNormal];
[_returnButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
}
return _returnButton;
}
@end
================================================
FILE: CTMediator/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
================================================
FILE: CTMediator/TableViewController/TableViewController.h
================================================
//
// TableViewController.h
// CTMediator
//
// Created by casa on 2016/10/20.
// Copyright © 2016年 casa. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TableViewController : UIViewController
@end
================================================
FILE: CTMediator/TableViewController/TableViewController.m
================================================
//
// TableViewController.m
// CTMediator
//
// Created by casa on 2016/10/20.
// Copyright © 2016年 casa. All rights reserved.
//
#import "TableViewController.h"
#import <HandyFrame/UIView+LayoutMethods.h>
#import "CTMediator+CTMediatorModuleAActions.h"
@interface TableViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UIButton *closeButton;
@end
@implementation TableViewController
#pragma mark - life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
[self.view addSubview:self.closeButton];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self.tableView fillWidth];
[self.tableView topInContainer:0 shouldResize:YES];
[self.tableView bottomInContainer:50 shouldResize:YES];
[self.closeButton fillWidth];
[self.closeButton top:0 FromView:self.tableView];
[self.closeButton bottomInContainer:0 shouldResize:YES];
}
- (void)dealloc
{
// 在Controller被回收的时候,把相关的target也回收掉
[[CTMediator sharedInstance] CTMediator_cleanTableViewCellTarget];
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// 通过Mediator来获取cell实例,由于target已经被cache了,高频调用不是问题。
[[CTMediator sharedInstance] CTMediator_configTableViewCell:cell withTitle:@"cell title" atIndexPath:indexPath];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 通过mediator来配置cell实例,由于target已经被cache了,高频调用不是问题。
return [[CTMediator sharedInstance] CTMediator_tableViewCellWithIdentifier:@"cell" tableView:tableView];
}
#pragma mark - event response
- (void)didTappedCloseButton:(UIButton *)button
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - getters and setters
- (UITableView *)tableView
{
if (_tableView == nil) {
_tableView = [[UITableView alloc] init];
_tableView.delegate = self;
_tableView.dataSource = self;
}
return _tableView;
}
- (UIButton *)closeButton
{
if (_closeButton == nil) {
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_closeButton setTitle:@"Close" forState:UIControlStateNormal];
[_closeButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(didTappedCloseButton:) forControlEvents:UIControlEventTouchUpInside];
_closeButton.backgroundColor = [UIColor grayColor];
}
return _closeButton;
}
@end
================================================
FILE: CTMediator/ViewController.h
================================================
//
// ViewController.h
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
================================================
FILE: CTMediator/ViewController.m
================================================
//
// ViewController.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import "ViewController.h"
#import <HandyFrame/UIView+LayoutMethods.h>
#import "CTMediator+CTMediatorModuleAActions.h"
#import "TableViewController.h"
NSString * const kCellIdentifier = @"kCellIdentifier";
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSArray *dataSource;
@end
@implementation ViewController
#pragma mark - life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self.tableView fill];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
cell.textLabel.text = self.dataSource[indexPath.row];
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.row == 0) {
UIViewController *viewController = [[CTMediator sharedInstance] CTMediator_viewControllerForDetail];
// 获得view controller之后,在这种场景下,到底push还是present,其实是要由使用者决定的,mediator只要给出view controller的实例就好了
[self presentViewController:viewController animated:YES completion:nil];
}
if (indexPath.row == 1) {
UIViewController *viewController = [[CTMediator sharedInstance] CTMediator_viewControllerForDetail];
[self.navigationController pushViewController:viewController animated:YES];
}
if (indexPath.row == 2) {
// 这种场景下,很明显是需要被present的,所以不必返回实例,mediator直接present了
[[CTMediator sharedInstance] CTMediator_presentImage:[UIImage imageNamed:@"image"]];
}
if (indexPath.row == 3) {
// 这种场景下,参数有问题,因此需要在流程中做好处理
[[CTMediator sharedInstance] CTMediator_presentImage:nil];
}
if (indexPath.row == 4) {
[[CTMediator sharedInstance] CTMediator_showAlertWithMessage:@"casa" cancelAction:nil confirmAction:^(NSDictionary *info) {
// 做你想做的事
}];
}
if (indexPath.row == 5) {
TableViewController *tableViewController = [[TableViewController alloc] init];
[self presentViewController:tableViewController animated:YES completion:nil];
}
if (indexPath.row == 6) {
[[CTMediator sharedInstance] performTarget:@"InvalidTarget" action:@"InvalidAction" params:nil shouldCacheTarget:NO];
}
}
#pragma mark - getters and setters
- (UITableView *)tableView
{
if (_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kCellIdentifier];
}
return _tableView;
}
- (NSArray *)dataSource
{
if (_dataSource == nil) {
_dataSource = @[@"present detail view controller",
@"push detail view controller",
@"present image",
@"present image when error",
@"show alert",
@"table view cell",
@"No Target-Action response"
];
}
return _dataSource;
}
@end
================================================
FILE: CTMediator/main.m
================================================
//
// main.m
// CTMediator
//
// Created by casa on 16/3/13.
// Copyright © 2016年 casa. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: CTMediator.podspec
================================================
#
# Be sure to run `pod spec lint CTMediator.podspec' to ensure this is a
# valid spec and to remove all comments including this before submitting the spec.
#
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#
Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# These will help people to find your library, and whilst it
# can feel like a chore to fill in it's definitely to your advantage. The
# summary should be tweet-length, and the description more in depth.
#
s.name = "CTMediator"
s.version = "48"
s.summary = "CTMediator."
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
s.description = "this is CTMediator"
s.homepage = "https://github.com/casatwy/CTMediator"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Licensing your code is important. See http://choosealicense.com for more info.
# CocoaPods will detect a license file if there is a named LICENSE*
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
#
# s.license = "MIT (example)"
s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the authors of the library, with email addresses. Email addresses
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
# accepts just a name if you'd rather not provide an email address.
#
# Specify a social_media_url where others can refer to, for example a twitter
# profile URL.
#
s.author = { "Casa Taloyum" => "casatwy@msn.com" }
# Or just: s.author = "Casa Taloyum"
# s.authors = { "Casa Taloyum" => "casatwy@msn.com" }
# s.social_media_url = "http://twitter.com/Casa Taloyum"
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If this Pod runs only on iOS or OS X, then specify the platform and
# the deployment target. You can optionally include the target after the platform.
#
# s.platform = :ios
# s.platform = :ios, "7.0"
# When using multiple platforms
s.ios.deployment_target = "7.0"
s.osx.deployment_target = "10.12"
# s.watchos.deployment_target = "2.0"
# s.tvos.deployment_target = "9.0"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Specify the location from where the source should be retrieved.
# Supports git, hg, bzr, svn and HTTP.
#
s.source = { :git => "https://github.com/casatwy/CTMediator.git", :tag => s.version.to_s }
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any swift, h, m, mm, c & cpp files.
# For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public.
#
s.source_files = "CTMediator/CTMediator/**/*.{h,m}"
# s.exclude_files = "Classes/Exclude"
# s.public_header_files = "Classes/**/*.h"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. Anything else will be cleaned.
# You can preserve files from being cleaned, please don't preserve
# non-essential files like tests, examples and documentation.
#
# s.resource = "icon.png"
# s.resources = "Resources/*.png"
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# Link your library with frameworks, or libraries. Libraries do not include
# the lib prefix of their name.
#
# s.framework = "UIKit"
s.frameworks = "Foundation", "CoreGraphics"
# s.library = "iconv"
# s.libraries = "iconv", "xml2"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# If your library depends on compiler flags you can set them in the xcconfig hash
# where they will only apply to your library. If you depend on other Podspecs
# you can include multiple dependencies to ensure it works.
# s.requires_arc = true
# s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
# s.dependency "JSONKit", "~> 1.4"
# s.dependency "CTHandyCategories"
end
================================================
FILE: CTMediator.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
4A5CE4FF1C9531C9006AEDB9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE4FE1C9531C9006AEDB9 /* main.m */; };
4A5CE5021C9531C9006AEDB9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */; };
4A5CE5051C9531C9006AEDB9 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5041C9531C9006AEDB9 /* ViewController.m */; };
4A5CE5081C9531C9006AEDB9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE5061C9531C9006AEDB9 /* Main.storyboard */; };
4A5CE50A1C9531C9006AEDB9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */; };
4A5CE50D1C9531C9006AEDB9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */; };
4A5CE51A1C95322F006AEDB9 /* CTMediator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5191C95322F006AEDB9 /* CTMediator.m */; };
4A5CE5251C953D7D006AEDB9 /* DemoModuleADetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */; };
4A5CE52B1C9547B2006AEDB9 /* Target_A.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A5CE52A1C9547B2006AEDB9 /* Target_A.m */; };
4A85F5541DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A85F5531DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.m */; };
4AC176591DE163B600566741 /* CTMediatorUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AC176581DE163B600566741 /* CTMediatorUITests.m */; };
4AD2E20524174B1900F8B53A /* CTMediator+HandyTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AD2E20424174B1900F8B53A /* CTMediator+HandyTools.m */; };
4AED66AE1DB895D900C13EDC /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AED66AD1DB895D900C13EDC /* TableViewController.m */; };
6A1C7FA419878A7AFA10DB7C /* libPods-CTMediator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CDD4389F5AEA1D8F6AA0C9F /* libPods-CTMediator.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
4AC1765B1DE163B600566741 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4A5CE4F21C9531C9006AEDB9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4A5CE4F91C9531C9006AEDB9;
remoteInfo = CTMediator;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
1CDD4389F5AEA1D8F6AA0C9F /* libPods-CTMediator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CTMediator.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2D583B83854D11618B8F5E65 /* Pods-CTMediator.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CTMediator.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CTMediator/Pods-CTMediator.debug.xcconfig"; sourceTree = "<group>"; };
4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CTMediator.app; sourceTree = BUILT_PRODUCTS_DIR; };
4A5CE4FE1C9531C9006AEDB9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
4A5CE5001C9531C9006AEDB9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
4A5CE5031C9531C9006AEDB9 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
4A5CE5041C9531C9006AEDB9 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
4A5CE5071C9531C9006AEDB9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4A5CE50C1C9531C9006AEDB9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
4A5CE50E1C9531C9006AEDB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4A5CE5181C95322F006AEDB9 /* CTMediator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTMediator.h; sourceTree = "<group>"; };
4A5CE5191C95322F006AEDB9 /* CTMediator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CTMediator.m; sourceTree = "<group>"; };
4A5CE5231C953D7D006AEDB9 /* DemoModuleADetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoModuleADetailViewController.h; sourceTree = "<group>"; };
4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoModuleADetailViewController.m; sourceTree = "<group>"; };
4A5CE5291C9547B2006AEDB9 /* Target_A.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Target_A.h; sourceTree = "<group>"; };
4A5CE52A1C9547B2006AEDB9 /* Target_A.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Target_A.m; sourceTree = "<group>"; };
4A85F5521DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CTMediator+CTMediatorModuleAActions.h"; sourceTree = "<group>"; };
4A85F5531DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CTMediator+CTMediatorModuleAActions.m"; sourceTree = "<group>"; };
4AC176561DE163B600566741 /* CTMediatorUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CTMediatorUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4AC176581DE163B600566741 /* CTMediatorUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CTMediatorUITests.m; sourceTree = "<group>"; };
4AC1765A1DE163B600566741 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4AD2E20324174B1900F8B53A /* CTMediator+HandyTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CTMediator+HandyTools.h"; sourceTree = "<group>"; };
4AD2E20424174B1900F8B53A /* CTMediator+HandyTools.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CTMediator+HandyTools.m"; sourceTree = "<group>"; };
4AED66AC1DB895D900C13EDC /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = "<group>"; };
4AED66AD1DB895D900C13EDC /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = "<group>"; };
E9C114EF1101F17773DD4798 /* Pods-CTMediator.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CTMediator.release.xcconfig"; path = "Pods/Target Support Files/Pods-CTMediator/Pods-CTMediator.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
4A5CE4F71C9531C9006AEDB9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6A1C7FA419878A7AFA10DB7C /* libPods-CTMediator.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4AC176531DE163B600566741 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4A5CE4F11C9531C9006AEDB9 = {
isa = PBXGroup;
children = (
4A5CE4FC1C9531C9006AEDB9 /* CTMediator */,
4AC176571DE163B600566741 /* CTMediatorUITests */,
4A5CE4FB1C9531C9006AEDB9 /* Products */,
B79600ED5E76116124B15CEE /* Pods */,
9449B9483205DCF29E913981 /* Frameworks */,
);
sourceTree = "<group>";
};
4A5CE4FB1C9531C9006AEDB9 /* Products */ = {
isa = PBXGroup;
children = (
4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */,
4AC176561DE163B600566741 /* CTMediatorUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
4A5CE4FC1C9531C9006AEDB9 /* CTMediator */ = {
isa = PBXGroup;
children = (
4AED66AB1DB895C600C13EDC /* TableViewController */,
4A85F5501DA92AFC00DB882C /* Categories(实际应用中,这是一个单独的repo,所用需要调度其他模块的人,只需要依赖这个repo。这个repo由target-action维护者维护) */,
4A5CE5141C9531E9006AEDB9 /* CTMediator(这也是单独的repo,完整的中间件就这100行代码) */,
4A5CE5211C953D5A006AEDB9 /* DemoModule(target-action所在的模块,也就是提供服务的模块,这也是单独的repo,但无需被其他人依赖,其他人通过category调用到这里的功能) */,
4A5CE5001C9531C9006AEDB9 /* AppDelegate.h */,
4A5CE5011C9531C9006AEDB9 /* AppDelegate.m */,
4A5CE5031C9531C9006AEDB9 /* ViewController.h */,
4A5CE5041C9531C9006AEDB9 /* ViewController.m */,
4A5CE5061C9531C9006AEDB9 /* Main.storyboard */,
4A5CE5091C9531C9006AEDB9 /* Assets.xcassets */,
4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */,
4A5CE50E1C9531C9006AEDB9 /* Info.plist */,
4A5CE4FD1C9531C9006AEDB9 /* Supporting Files */,
);
path = CTMediator;
sourceTree = "<group>";
};
4A5CE4FD1C9531C9006AEDB9 /* Supporting Files */ = {
isa = PBXGroup;
children = (
4A5CE4FE1C9531C9006AEDB9 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
4A5CE5141C9531E9006AEDB9 /* CTMediator(这也是单独的repo,完整的中间件就这100行代码) */ = {
isa = PBXGroup;
children = (
4A5CE5181C95322F006AEDB9 /* CTMediator.h */,
4A5CE5191C95322F006AEDB9 /* CTMediator.m */,
4AD2E20324174B1900F8B53A /* CTMediator+HandyTools.h */,
4AD2E20424174B1900F8B53A /* CTMediator+HandyTools.m */,
);
name = "CTMediator(这也是单独的repo,完整的中间件就这100行代码)";
path = CTMediator;
sourceTree = "<group>";
};
4A5CE5211C953D5A006AEDB9 /* DemoModule(target-action所在的模块,也就是提供服务的模块,这也是单独的repo,但无需被其他人依赖,其他人通过category调用到这里的功能) */ = {
isa = PBXGroup;
children = (
4A5CE5221C953D5A006AEDB9 /* Actions */,
4A5CE5231C953D7D006AEDB9 /* DemoModuleADetailViewController.h */,
4A5CE5241C953D7D006AEDB9 /* DemoModuleADetailViewController.m */,
);
name = "DemoModule(target-action所在的模块,也就是提供服务的模块,这也是单独的repo,但无需被其他人依赖,其他人通过category调用到这里的功能)";
path = DemoModule;
sourceTree = "<group>";
};
4A5CE5221C953D5A006AEDB9 /* Actions */ = {
isa = PBXGroup;
children = (
4A5CE5291C9547B2006AEDB9 /* Target_A.h */,
4A5CE52A1C9547B2006AEDB9 /* Target_A.m */,
);
path = Actions;
sourceTree = "<group>";
};
4A85F5501DA92AFC00DB882C /* Categories(实际应用中,这是一个单独的repo,所用需要调度其他模块的人,只需要依赖这个repo。这个repo由target-action维护者维护) */ = {
isa = PBXGroup;
children = (
4A85F5511DA92AFC00DB882C /* ModuleA */,
);
name = "Categories(实际应用中,这是一个单独的repo,所用需要调度其他模块的人,只需要依赖这个repo。这个repo由target-action维护者维护)";
path = Categories;
sourceTree = "<group>";
};
4A85F5511DA92AFC00DB882C /* ModuleA */ = {
isa = PBXGroup;
children = (
4A85F5521DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.h */,
4A85F5531DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.m */,
);
path = ModuleA;
sourceTree = "<group>";
};
4AC176571DE163B600566741 /* CTMediatorUITests */ = {
isa = PBXGroup;
children = (
4AC176581DE163B600566741 /* CTMediatorUITests.m */,
4AC1765A1DE163B600566741 /* Info.plist */,
);
path = CTMediatorUITests;
sourceTree = "<group>";
};
4AED66AB1DB895C600C13EDC /* TableViewController */ = {
isa = PBXGroup;
children = (
4AED66AC1DB895D900C13EDC /* TableViewController.h */,
4AED66AD1DB895D900C13EDC /* TableViewController.m */,
);
path = TableViewController;
sourceTree = "<group>";
};
9449B9483205DCF29E913981 /* Frameworks */ = {
isa = PBXGroup;
children = (
1CDD4389F5AEA1D8F6AA0C9F /* libPods-CTMediator.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
B79600ED5E76116124B15CEE /* Pods */ = {
isa = PBXGroup;
children = (
2D583B83854D11618B8F5E65 /* Pods-CTMediator.debug.xcconfig */,
E9C114EF1101F17773DD4798 /* Pods-CTMediator.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
4A5CE4F91C9531C9006AEDB9 /* CTMediator */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4A5CE5111C9531C9006AEDB9 /* Build configuration list for PBXNativeTarget "CTMediator" */;
buildPhases = (
9F6811B15C0C49802EEE481B /* [CP] Check Pods Manifest.lock */,
0DEB0101A9257C7385F33550 /* [CP] Check Pods Manifest.lock */,
4A5CE4F61C9531C9006AEDB9 /* Sources */,
4A5CE4F71C9531C9006AEDB9 /* Frameworks */,
4A5CE4F81C9531C9006AEDB9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = CTMediator;
productName = CTMediator;
productReference = 4A5CE4FA1C9531C9006AEDB9 /* CTMediator.app */;
productType = "com.apple.product-type.application";
};
4AC176551DE163B600566741 /* CTMediatorUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4AC1765F1DE163B600566741 /* Build configuration list for PBXNativeTarget "CTMediatorUITests" */;
buildPhases = (
4AC176521DE163B600566741 /* Sources */,
4AC176531DE163B600566741 /* Frameworks */,
4AC176541DE163B600566741 /* Resources */,
);
buildRules = (
);
dependencies = (
4AC1765C1DE163B600566741 /* PBXTargetDependency */,
);
name = CTMediatorUITests;
productName = CTMediatorUITests;
productReference = 4AC176561DE163B600566741 /* CTMediatorUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
4A5CE4F21C9531C9006AEDB9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = casa;
TargetAttributes = {
4A5CE4F91C9531C9006AEDB9 = {
CreatedOnToolsVersion = 7.2.1;
DevelopmentTeam = THS9SRQVES;
};
4AC176551DE163B600566741 = {
CreatedOnToolsVersion = 8.1;
DevelopmentTeam = THS9SRQVES;
ProvisioningStyle = Automatic;
TestTargetID = 4A5CE4F91C9531C9006AEDB9;
};
};
};
buildConfigurationList = 4A5CE4F51C9531C9006AEDB9 /* Build configuration list for PBXProject "CTMediator" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = 4A5CE4F11C9531C9006AEDB9;
productRefGroup = 4A5CE4FB1C9531C9006AEDB9 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
4A5CE4F91C9531C9006AEDB9 /* CTMediator */,
4AC176551DE163B600566741 /* CTMediatorUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
4A5CE4F81C9531C9006AEDB9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4A5CE50D1C9531C9006AEDB9 /* LaunchScreen.storyboard in Resources */,
4A5CE50A1C9531C9006AEDB9 /* Assets.xcassets in Resources */,
4A5CE5081C9531C9006AEDB9 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4AC176541DE163B600566741 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0DEB0101A9257C7385F33550 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
9F6811B15C0C49802EEE481B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-CTMediator-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
4A5CE4F61C9531C9006AEDB9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4A5CE5051C9531C9006AEDB9 /* ViewController.m in Sources */,
4A5CE5021C9531C9006AEDB9 /* AppDelegate.m in Sources */,
4A85F5541DA92AFC00DB882C /* CTMediator+CTMediatorModuleAActions.m in Sources */,
4A5CE4FF1C9531C9006AEDB9 /* main.m in Sources */,
4A5CE5251C953D7D006AEDB9 /* DemoModuleADetailViewController.m in Sources */,
4A5CE51A1C95322F006AEDB9 /* CTMediator.m in Sources */,
4AD2E20524174B1900F8B53A /* CTMediator+HandyTools.m in Sources */,
4A5CE52B1C9547B2006AEDB9 /* Target_A.m in Sources */,
4AED66AE1DB895D900C13EDC /* TableViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4AC176521DE163B600566741 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4AC176591DE163B600566741 /* CTMediatorUITests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
4AC1765C1DE163B600566741 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4A5CE4F91C9531C9006AEDB9 /* CTMediator */;
targetProxy = 4AC1765B1DE163B600566741 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
4A5CE5061C9531C9006AEDB9 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
4A5CE5071C9531C9006AEDB9 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
4A5CE50B1C9531C9006AEDB9 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
4A5CE50C1C9531C9006AEDB9 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
4A5CE50F1C9531C9006AEDB9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4A5CE5101C9531C9006AEDB9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
4A5CE5121C9531C9006AEDB9 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2D583B83854D11618B8F5E65 /* Pods-CTMediator.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = THS9SRQVES;
INFOPLIST_FILE = CTMediator/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediator;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
4A5CE5131C9531C9006AEDB9 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E9C114EF1101F17773DD4798 /* Pods-CTMediator.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = THS9SRQVES;
INFOPLIST_FILE = CTMediator/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediator;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
4AC1765D1DE163B600566741 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
DEVELOPMENT_TEAM = THS9SRQVES;
INFOPLIST_FILE = CTMediatorUITests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediatorUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_TARGET_NAME = CTMediator;
};
name = Debug;
};
4AC1765E1DE163B600566741 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
DEVELOPMENT_TEAM = THS9SRQVES;
INFOPLIST_FILE = CTMediatorUITests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = casa.CTMediatorUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_TARGET_NAME = CTMediator;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
4A5CE4F51C9531C9006AEDB9 /* Build configuration list for PBXProject "CTMediator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4A5CE50F1C9531C9006AEDB9 /* Debug */,
4A5CE5101C9531C9006AEDB9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4A5CE5111C9531C9006AEDB9 /* Build configuration list for PBXNativeTarget "CTMediator" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4A5CE5121C9531C9006AEDB9 /* Debug */,
4A5CE5131C9531C9006AEDB9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4AC1765F1DE163B600566741 /* Build configuration list for PBXNativeTarget "CTMediatorUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4AC1765D1DE163B600566741 /* Debug */,
4AC1765E1DE163B600566741 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 4A5CE4F21C9531C9006AEDB9 /* Project object */;
}
================================================
FILE: CTMediator.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:CTMediator.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/CTMediator.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4A5CE4F91C9531C9006AEDB9"
BuildableName = "CTMediator.app"
BlueprintName = "CTMediator"
ReferencedContainer = "container:CTMediator.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4AC176551DE163B600566741"
BuildableName = "CTMediatorUITests.xctest"
BlueprintName = "CTMediatorUITests"
ReferencedContainer = "container:CTMediator.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4A5CE4F91C9531C9006AEDB9"
BuildableName = "CTMediator.app"
BlueprintName = "CTMediator"
ReferencedContainer = "container:CTMediator.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4A5CE4F91C9531C9006AEDB9"
BuildableName = "CTMediator.app"
BlueprintName = "CTMediator"
ReferencedContainer = "container:CTMediator.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4A5CE4F91C9531C9006AEDB9"
BuildableName = "CTMediator.app"
BlueprintName = "CTMediator"
ReferencedContainer = "container:CTMediator.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>CTMediator.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>4A5CE4F91C9531C9006AEDB9</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>4AC176551DE163B600566741</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: CTMediatorUITests/CTMediatorUITests.m
================================================
//
// CTMediatorUITests.m
// CTMediatorUITests
//
// Created by casa on 2016/11/20.
// Copyright © 2016年 casa. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface CTMediatorUITests : XCTestCase
@end
@implementation CTMediatorUITests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
self.continueAfterFailure = YES;
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
[[[XCUIApplication alloc] init] launch];
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testPresentDetailViewController
{
XCUIApplication *app = [[XCUIApplication alloc] init];
[app.tables.staticTexts[@"present detail view controller"] tap];
[app.buttons[@"return"] tap];
XCTAssertTrue(app.exists);
}
- (void)testCrashTableViewController
{
XCUIApplication *app = [[XCUIApplication alloc] init];
XCUIElement *cellToCrash = app.tables.staticTexts[@"table view cell"];
[cellToCrash tap];
XCTAssertTrue(app.exists);
}
@end
================================================
FILE: CTMediatorUITests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: FILE_LICENSE
================================================
MIT
================================================
FILE: Podfile
================================================
# Uncomment this line to define a global platform for your project
# platform :ios, '8.0'
# Uncomment this line if you're using Swift
# use_frameworks!
target 'CTMediator' do
pod "HandyFrame"
# pod "CTHandyCategories"
end
================================================
FILE: readme.md
================================================
CTMediator
==========
objective-c:
```
pod "CTMediator"
```
swift:
```
use_frameworks!
pod "CTMediator"
```
---
`CTMediator` helps you to divide your project into multi-project, and use `Target-Action` pattern to let subprojects to communicate with each other. *with no regist process!*
you can check demo for more details:
[Origin project](https://github.com/ModulizationDemo/MainProject)
[Modulized Main Project with CTMediator](https://github.com/ModulizationDemo/ModulizedMainProject)
[Demos](https://github.com/ModulizationDemo)
[Swift Demo](https://github.com/ModulizationDemo/SwfitDemo)
add private repo before you run demos:
```
pod repo add PrivatePods https://github.com/ModulizationDemo/PrivatePods.git
```
remember to run `pod install` before you run the demo!
---
[Origin project](https://github.com/ModulizationDemo/MainProject)
[Modulized Main Project with CTMediator](https://github.com/ModulizationDemo/ModulizedMainProject)
[Demos](https://github.com/ModulizationDemo)
[Swift Demo](https://github.com/ModulizationDemo/SwfitDemo)
跑demo时先添加私有库:
```
pod repo add PrivatePods https://github.com/ModulizationDemo/PrivatePods.git
```
然后就可以`pod install`了
---
[iOS应用架构谈 组件化方案](http://casatwy.com/iOS-Modulization.html)
[在现有工程中实施基于CTMediator的组件化方案](http://casatwy.com/modulization_in_action.html)
[CTMediator的Swift应用](https://casatwy.com/CTMediator_in_Swift.html)
---
本工程其实也是个Demo
`Category`目录在实际工程中是单独的一个repo,调用者通过依赖category这个repo来完成功能调度。一般来说是每一个业务对应一个category的repo。因此调用者需要调度哪个业务,就依赖哪个业务的category。category这个repo由对应提供服务的业务来维护。
`CTMediator`目录在实际工程中也是一个单独的repo,仅用于存放中间件。被每一个业务线各自维护的category repo所依赖。
`DemoModule`目录是实际提供服务的业务,这个在实际工程中也是一个单独的repo。这个repo不被任何人所依赖,这个repo通过target-action来提供被调度的功能,然后由category repo通过runtime调度。
---
`CTMediator` helps you to divide your project into multi-project, and use `Target-Action` pattern to let subprojects to communicate with each other.
you can check demo for more details:
[Demo](https://github.com/ModulizationDemo)
[Swift Demo](https://github.com/ModulizationDemo/SwfitDemo)
================================================
FILE: upload.sh
================================================
#!/bin/bash
git stash
git pull origin master --tags
git stash pop
VersionString=`grep -E 's.version.*=' CTMediator.podspec`
VersionNumber=`tr -cd 0-9 <<<"$VersionString"`
NewVersionNumber=$(($VersionNumber + 1))
LineNumber=`grep -nE 's.version.*=' CTMediator.podspec | cut -d : -f1`
git add .
git commit -am modification
git pull origin master --tags
sed -i "" "${LineNumber}s/${VersionNumber}/${NewVersionNumber}/g" CTMediator.podspec
echo "current version is ${VersionNumber}, new version is ${NewVersionNumber}"
git commit -am ${NewVersionNumber}
git tag ${NewVersionNumber}
git push origin master --tags
pod trunk push ./CTMediator.podspec --verbose --use-libraries --allow-warnings
gitextract_58u0q7qj/ ├── .gitignore ├── .swift-version ├── CTMediator/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets/ │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── image.imageset/ │ │ │ └── Contents.json │ │ └── noImage.imageset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── CTMediator/ │ │ ├── CTMediator+HandyTools.h │ │ ├── CTMediator+HandyTools.m │ │ ├── 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 │ ├── TableViewController/ │ │ ├── TableViewController.h │ │ └── TableViewController.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── CTMediator.podspec ├── CTMediator.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcuserdata/ │ └── casa.xcuserdatad/ │ └── xcschemes/ │ ├── CTMediator.xcscheme │ └── xcschememanagement.plist ├── CTMediatorUITests/ │ ├── CTMediatorUITests.m │ └── Info.plist ├── FILE_LICENSE ├── Podfile ├── readme.md └── upload.sh
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (93K chars).
[
{
"path": ".gitignore",
"chars": 112,
"preview": "CTMediator.xcworkspace/\nPodfile.lock\nPods/\nCTMediator.xcodeproj/project.xcworkspace/xcuserdata/\n.DS_Store\n*.swp\n"
},
{
"path": ".swift-version",
"chars": 4,
"preview": "3.0\n"
},
{
"path": "CTMediator/AppDelegate.h",
"chars": 267,
"preview": "//\n// AppDelegate.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n"
},
{
"path": "CTMediator/AppDelegate.m",
"chars": 2252,
"preview": "//\n// AppDelegate.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n"
},
{
"path": "CTMediator/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1590,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"size\" : \"20x20\",\n \"scale\" : \"2x\"\n },\n {\n \"idiom\""
},
{
"path": "CTMediator/Assets.xcassets/Contents.json",
"chars": 62,
"preview": "{\n \"info\" : {\n \"version\" : 1,\n \"author\" : \"xcode\"\n }\n}"
},
{
"path": "CTMediator/Assets.xcassets/image.imageset/Contents.json",
"chars": 302,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"filename\" : \"image.png\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "CTMediator/Assets.xcassets/noImage.imageset/Contents.json",
"chars": 304,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"filename\" : \"noImage.png\",\n \"scale\" : \"1x\"\n },\n {\n"
},
{
"path": "CTMediator/Base.lproj/LaunchScreen.storyboard",
"chars": 1664,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "CTMediator/Base.lproj/Main.storyboard",
"chars": 2670,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "CTMediator/CTMediator/CTMediator+HandyTools.h",
"chars": 900,
"preview": "//\n// CTMediator+HandyTools.h\n// CTMediator\n//\n// Created by casa on 2020/3/10.\n// Copyright © 2020 casa. All rights"
},
{
"path": "CTMediator/CTMediator/CTMediator+HandyTools.m",
"chars": 2826,
"preview": "//\n// CTMediator+HandyTools.m\n// CTMediator\n//\n// Created by casa on 2020/3/10.\n// Copyright © 2020 casa. All rights"
},
{
"path": "CTMediator/CTMediator/CTMediator.h",
"chars": 896,
"preview": "//\n// CTMediator.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n/"
},
{
"path": "CTMediator/CTMediator/CTMediator.m",
"chars": 8558,
"preview": "//\n// CTMediator.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n/"
},
{
"path": "CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.h",
"chars": 831,
"preview": "//\n// CTMediator+CTMediatorModuleAActions.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 cas"
},
{
"path": "CTMediator/Categories/ModuleA/CTMediator+CTMediatorModuleAActions.m",
"chars": 3689,
"preview": "//\n// CTMediator+CTMediatorModuleAActions.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 cas"
},
{
"path": "CTMediator/DemoModule/Actions/Target_A.h",
"chars": 464,
"preview": "//\n// Target_A.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n//\n"
},
{
"path": "CTMediator/DemoModule/Actions/Target_A.m",
"chars": 3487,
"preview": "//\n// Target_A.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n//\n"
},
{
"path": "CTMediator/DemoModule/DemoModuleADetailViewController.h",
"chars": 363,
"preview": "//\n// DemoModuleADetailViewController.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. A"
},
{
"path": "CTMediator/DemoModule/DemoModuleADetailViewController.m",
"chars": 2509,
"preview": "//\n// DemoModuleADetailViewController.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. A"
},
{
"path": "CTMediator/Info.plist",
"chars": 1495,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "CTMediator/TableViewController/TableViewController.h",
"chars": 216,
"preview": "//\n// TableViewController.h\n// CTMediator\n//\n// Created by casa on 2016/10/20.\n// Copyright © 2016年 casa. All rights"
},
{
"path": "CTMediator/TableViewController/TableViewController.m",
"chars": 2831,
"preview": "//\n// TableViewController.m\n// CTMediator\n//\n// Created by casa on 2016/10/20.\n// Copyright © 2016年 casa. All rights"
},
{
"path": "CTMediator/ViewController.h",
"chars": 205,
"preview": "//\n// ViewController.h\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserve"
},
{
"path": "CTMediator/ViewController.m",
"chars": 3782,
"preview": "//\n// ViewController.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserve"
},
{
"path": "CTMediator/main.m",
"chars": 324,
"preview": "//\n// main.m\n// CTMediator\n//\n// Created by casa on 16/3/13.\n// Copyright © 2016年 casa. All rights reserved.\n//\n\n#im"
},
{
"path": "CTMediator.podspec",
"chars": 5056,
"preview": "#\n# Be sure to run `pod spec lint CTMediator.podspec' to ensure this is a\n# valid spec and to remove all comments incl"
},
{
"path": "CTMediator.xcodeproj/project.pbxproj",
"chars": 27198,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "CTMediator.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 155,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:CTMediator.xcod"
},
{
"path": "CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/CTMediator.xcscheme",
"chars": 3782,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0930\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "CTMediator.xcodeproj/xcuserdata/casa.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 572,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "CTMediatorUITests/CTMediatorUITests.m",
"chars": 1505,
"preview": "//\n// CTMediatorUITests.m\n// CTMediatorUITests\n//\n// Created by casa on 2016/11/20.\n// Copyright © 2016年 casa. All r"
},
{
"path": "CTMediatorUITests/Info.plist",
"chars": 680,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "FILE_LICENSE",
"chars": 4,
"preview": "MIT\n"
},
{
"path": "Podfile",
"chars": 226,
"preview": "# Uncomment this line to define a global platform for your project\n# platform :ios, '8.0'\n# Uncomment this line if you'r"
},
{
"path": "readme.md",
"chars": 2058,
"preview": "CTMediator\n==========\n\nobjective-c:\n\n```\npod \"CTMediator\"\n```\n\nswift:\n\n```\nuse_frameworks!\npod \"CTMediator\"\n```\n\n---\n\n\n`"
},
{
"path": "upload.sh",
"chars": 693,
"preview": "#!/bin/bash\n\ngit stash\ngit pull origin master --tags\ngit stash pop\n\nVersionString=`grep -E 's.version.*=' CTMediator.pod"
}
]
About this extraction
This page contains the full source code of the casatwy/CTMediator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (82.6 KB), approximately 25.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.