Giter Club home page Giter Club logo

ctmediator's People

Contributors

casatwy avatar fanyizeng avatar plan-do-break-fix avatar woonoah avatar xwlxwl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ctmediator's Issues

What does a URL represent ?

Thanks for your CTMediator, it is very impressive for me.

And there is a question coming into my mind, that is what does a URL represent?

In many apps, a URL, with host, path and action , stands for an individual page, which is commonly considered as a controller. Thus when we open a scheme, we will actually open a new page.

But in CTMediator, when we are trying to open a URL, we are actually calling a service method, without respect to what is serving backwards.

I'm wandering what will you do when you are trying to implement open url as page via CTMediator ?

不传参崩溃

如果action不接受参数的话,就时不时的崩溃掉。 设计中 action是一定要传参的吗?

Hello,casatwy,想咨询一个关于error的处理

结合自己的项目,加上您的这个框架,写了一套适合自己项目的Mediator,为了确保框架的稳定性,我接入了大量的单元测试,通过NSError **的方式能够将框架内部的error传出.有一个问题需要请教一下哈

  • 1.在看了您的文章后在swift层,也准备接入,我打算在单元测试中测试您说的swift -> extension -> swift这八种情况,但是因为swift2.0后error的抛出只能使用throw,那么如何能在swift的单元测试中检测到Objc抛出的error呢

  • 2.您的代码链接在135行关于返回值的判断,其实是不足的,因为缺少很多种情况,走单元测试会导致崩溃,您是出于对项目返回值的一个规范吗

你好,我在swift下用这个框架发现类的时候一直找不到target

请问是我的代码有什么错误吗~一直没搞好,本来工程构建到一半卡住了

调用:override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let vc = CTMediator.sharedInstance().performTarget("T", action: "test", params: nil, shouldCacheTarget: false) navigationController!.pushViewController(vc! as! UIViewController, animated: true) }

target:class Target_T_: NSObject { func Action_test(params: [AnyHashable : Any]) -> UIViewController { return UIViewController() } }

pod install报错

An unexpected version directory Assets.xcassets was encountered for the /Users/longmin/.cocoapods/repos/CTMediator/CTMediator Pod in the CTMediator repository.

CTMediator源码疑问

casa老师,你好;

CTMediator类中方法有个疑问,target中有些方法是不需要参数的
performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget中
下面这两行代码就不是很合理了
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];

actionString = [NSString stringWithFormat:@"Action_%@WithParmas:",actionName];

我觉得“:” 写到Mediator的category中对actionName的声明中,
如 NSString * const kCTMediatorActionNativFetchDetailViewController = @"nativeFetchDetailViewController:";
这样是不是合理一些?

这样的话,在performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget方法中,需要针对action是否是带参数进行区分是调用 [target performSelector:action]还是 [target performSelector:action withObject:params]

小问题

DemoModuleADetailViewController.m 文件中 41 和 44 行 size 是不是ct_size?

swift

为什么mediator基类不能用纯swift实现?遇到什么困难了吗? @casatwy

有一种使用场景

你好,目前应用中有这样一种使用场景:
模块A中有个广告业务,广告有很多中接口,但最终都能转成一种view model
现在有模块B,它想通过路由使用A模块提供的广告功能,界面稍有不同,view model可以共用,那我如何通过target-action这种形式的路由实现这种场景呢?

模块与模块之间如何调用

您好,我想问一下模块与模块间如何调用呢?通过导入分类的方式?如果是这样的话,模块间会有耦合呐.

swift使用CTMediator,target总为nil?导致闪退

背景:
项目语言swift,直接在项目文件下创建了业务模块,创建了target extension文件夹,kCTMediatorParamsKeySwiftTargetModuleName参数传入的是target所在的文件夹名字,使用的时候因为target为nil导致controller为nil,闪退。
有尝试过将demo中的A_swift文件夹放入demo项目中也出现闪退。
疑问:
swift项目中想使用CTMediator使用必须将业务模块做成cocoapods库才可以?
如果必须做成cocoapods库,那么开发的时候如何直接使用CTMediator?

请教一个问题:事件如何外向传递

#11 感觉有点类似这个问题
就是业务A中的事件如何传递到主工程中去响应?
业务A对应TargetA。业务A点击事件可以通过通知传递到TargetA中。但是业务A对应的CTMediator_A 如何在主工程中接收响应呢?
求指教

safePerformAction 的返回参数类型局限性,且只支持单个参数

  • (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:&params 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:&params 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:&params 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:&params 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:&params 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
}

下面的方法是不是更好点

  • (id)getReturnValueInvocatein:(NSInvocation *)invocation
    {

    const char *returnType = invocation.methodSignature.methodReturnType;
    // Skip const type qualifier.
    if (returnType[0] == 'r') {
    returnType++;
    }

    if (strcmp(returnType, @encode(id)) == 0 || strcmp(returnType, @encode(Class)) == 0 || strcmp(returnType, @encode(void (^)(void))) == 0) {
    __autoreleasing id returnObj;
    [invocation getReturnValue:&returnObj];
    return returnObj;
    } else if (strcmp(returnType, @encode(char)) == 0) {
    WRAP_GET_VALUE(char);
    } else if (strcmp(returnType, @encode(int)) == 0) {
    WRAP_GET_VALUE(int);
    } else if (strcmp(returnType, @encode(short)) == 0) {
    WRAP_GET_VALUE(short);
    } else if (strcmp(returnType, @encode(long)) == 0) {
    WRAP_GET_VALUE(long);
    } else if (strcmp(returnType, @encode(long long)) == 0) {
    WRAP_GET_VALUE(long long);
    } else if (strcmp(returnType, @encode(unsigned char)) == 0) {
    WRAP_GET_VALUE(unsigned char);
    } else if (strcmp(returnType, @encode(unsigned int)) == 0) {
    WRAP_GET_VALUE(unsigned int);
    } else if (strcmp(returnType, @encode(unsigned short)) == 0) {
    WRAP_GET_VALUE(unsigned short);
    } else if (strcmp(returnType, @encode(unsigned long)) == 0) {
    WRAP_GET_VALUE(unsigned long);
    } else if (strcmp(returnType, @encode(unsigned long long)) == 0) {
    WRAP_GET_VALUE(unsigned long long);
    } else if (strcmp(returnType, @encode(float)) == 0) {
    WRAP_GET_VALUE(float);
    } else if (strcmp(returnType, @encode(double)) == 0) {
    WRAP_GET_VALUE(double);
    } else if (strcmp(returnType, @encode(BOOL)) == 0) {
    WRAP_GET_VALUE(BOOL);
    } else if (strcmp(returnType, @encode(char *)) == 0) {
    WRAP_GET_VALUE(const char *);
    } else if (strcmp(returnType, @encode(void)) == 0) {
    return nil;
    } else {
    NSUInteger valueSize = 0;
    NSGetSizeAndAlignment(returnType, &valueSize, NULL);

      unsigned char valueBytes[valueSize];
      [invocation getReturnValue:valueBytes];
      
      return [NSValue valueWithBytes:valueBytes objCType:returnType];
    

    }

    return nil;

#undef WRAP_AND_RETURN
}

参数问题

您好,请教一下为什么参数是字典类型?换成 id 不是更好吗?实际上直接传id类型也是ok的,比如NSNumber、NSData。不知是否另有用意,望大佬赐教 @casatwy

safePerformAction这个方法里面的校验是什么意思?

  • (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:&params 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:&params 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:&params 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:&params 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:&params 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
}
这个方法里面的校验是什么意思?有什么作用

请教下问题!

目前正在研究您的组件化开发方式,但是遇到一个问题,就是我再businessA中用到的MediatorB, 在businessB中用到了MediatorA,然后我再demo中引入了这两个 businessA、businessB,工程就无法编译通过,麻烦大神帮忙指导下

businessA(依赖了MediatorB,通过分类调用了B业务的方法) 、businessB(依赖了MediatorA,通过分类调用了A业务的方法) 、MediatorA(依赖CTMediator)、MediatorB(依赖CTMediator) 都是单独的pod库
把 pod 'BusinessB', '> 0.4.0'
pod 'BusinessA', '
> 0.7.0'
这两个一起引入后工程就报错:Apple Mach-O-Linker Error

单独使用就没错~~

Swift中NSClassFromString需要添加命名空间才能获得类

在Swift工程中
NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
targetClass = NSClassFromString(targetClassString);
targetClass 为nil,后面应该在取一次targetClassString = [NSString stringWithFormat:@"工程名.Target_%@", targetName];

关于组件之间的互相调用和组件生命周期

场景

  • 组件管理库M 包含CTMediator
  • 组件A和组件B,它们相互独立并在不同的仓库。M能知道组件A和组件B,但是默认情况下,组件A和组件B并不知道M

需求

  1. 组件A和组件B如何互相调用?或如何通过M来通信?
  2. 如果组件A和组件B都有生命周期:如初始化、登录、退出、反初始化,该如何实现?

麻烦大神解答,非常感谢。

说明: 组件A和组件B如何互相调用, 尽量不要考虑组件都包含CTMediator的情况。因为这样的话,写一个头文件协议是不是更简单?
另外,组件A和组件B只是方便说明,这里要考虑的情况就是有很多个组件,至少具体多少个也只是程序运行后才知道的。

内存问题

Class targetClass = NSClassFromString(targetClassString);
id target = [[targetClass alloc] init];
SEL action = NSSelectorFromString(actionString);
这样不是每perform一次都会新生成一个target,调多了内存怎么管理

关于单例model的使用问题

尊敬的作者你好,
我想问一下,如果平台有类似于userManger这种单例对象,各业务线想要获取该对象应该怎么处理?
该对象拥有一些user属性,另外还会存在多种类似于register,clear的方法,业务方可能需要调用[UserManger shareManager].userName或[[UserManger shareManager] register]。
其中方法可以category映射出来,属性也可以写一个get方法通过字典传出来。
我想请问的是,在实际使用中有没有更好的方法?

想咨询一个问题?

一个业务组件对应一个pod target的入口?为什么不将所有的target 入口放在同一个pod 里面呢?

有问题求教

“直接把整个model层组件化后暴露给所有组件,容易造成数据泄露,付出的代价有点大”
这句话我没理解造成数据泄露是什么意思,可否举个例子
付出的代价是什么?可否举个例子

是否考虑让用户自己处理无响应请求?

发现升级到swift 4.0之后,重新更新后引入了CTHandyCategories,查看源码就是处理无响应请求的时候弹出一个alertview。对于稍微有点代码洁癖的码农来说,不希望引入额外的代码文件~
#####建议让用户自己处理无响应的情况,改进如下:

typedef id(^NoTargetActionHandler)(NSString *targetName, NSString *actionName)

@interface CTMediator : NSObject

@property (nonatomic, copy) NoTargetActionHandler handler;

@end

然后使用handler替换掉[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString];,这样可以去掉对CTHandyCategories,同时也可以让用户自己处理无响应的情况。

你好,swift 4.2,调用不到主项目的方法

  • Swift Version:4.2
  • Xcode Version :10.0
  • CTMediator (25)
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];
            [self.cachedTarget removeObjectForKey:targetClassString];
            return nil;
        }
    }
  • swift-demo也运行不正确

此处判断走的是else,不知道是什么原因,之前swift4.0的时候代码是可以运行的。

项目跑不起来呢?

pod install 之后, 项目跑不起来, 提示:
ld: warning: directory not found for option '-L/Users/greatman/Library/Developer/Xcode/DerivedData/CTMediator-bmljppouvvqrztaquakdqpyyykij/Build/Products/Debug-iphonesimulator/HandyFrame'
ld: library not found for -lHandyFrame
clang: error: linker command failed with exit code 1 (use -v to see invocation)
好像是没有lHandyFrame这个东西...

UI的组件化问题

大神你好,看了你的iOS组件化方案,受益颇深,目前我也在对公司的项目进行组件化重构,现在遇到这个问题:
我觉得项目中的一些通用UI也应该作为一个组件存在,那么在使用UI组件的过程中,就免不了在对组件实例化之后进行赋值等操作,比如UITableViewCell,必然要在复用时进行赋值操作,而复用就意味着cell实例已经存在。在您的方案中,只能在获取实例的同时对实例进行操作,对已存在的实例却无能为力,我想请教下您针对这种情况有没有什么好的方案,谢谢

在workspace里找不到target

我没有用私有pod去分离组件,而是每个组件对应一个单独的project放在workspace里。很好奇为什么这样在其他类里执行的时候会初始化target不成功,targetClass地址也没有是0X0.只有当我把子组件里的对应的Target_XX.h暴露在需要调用的其他组件,并且初始化一个对象的时候才能在您的库里初始化成功。而且试了试我如果只导入这个.h,没有初始化也无法初始化成功,必须得和下图一样手动调一下才行。是我有什么操作不当的地方吗
`- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

Target_Index *target = [Target_Index new];`
UIViewController *vc = [[CTMediator sharedInstance] index_viewControllerWithTitle:@"测试"];

}

methodSignatureForSelector 获取问题nil 问题?必现

NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
第一次:在 tagetA 中创建一个方法A 组件化调用 methodSig 正常获取,
第二次:修改tagetA中方法 A的名字,修改 action 字符串名称之后,运行 methodSig返回 nil,重启 xcode之后 methodSig可以正常获取。
环境 xcode10.2

重复

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.tableView fill];
}

这样写是否才好?

- (void)viewWillLayoutSubviews
{
    [self.tableView fill];
}

Target与Category都用swift编写,不能跳转

您好,主要是方法那里不能识别出来。

// 有可能target是Swift对象
        actionString = [NSString stringWithFormat:@"Action_%@WithParams:", actionName];
        action = NSSelectorFromString(actionString);
        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.cachedTarget removeObjectForKey:targetClassString];
                return nil;
            }
        }

上面这一断,进入到了else里面。

我的demo代码中,Target_Register.swift文件代码出下:
Target中代码如下:
@objc(Target_Register)
class Target_Register: NSObject {

func Action_registerViewController(params: [String:Any]) -> XYJBaseVC {
    let vc = XYJRegisterVC()
    return vc
}

}

category中代码如下:
// 1. 字符串 是类名 Target_xxx.h 中的 xxx 部分
let kCTMediatorTarget_Register = "Register"

// 2. 字符串是 Target_xxx.h 中 定义的 Action_xxxx 函数名的 xxx 部分
let kCTMediatorActionNavigaTo_RegisterVC = "registerViewController"

extension CTMediator {

func ylx_mediator_registerVCWithParams(params: [String:Any]) -> XYJBaseVC {
    
    if let registerVc = performTarget(kCTMediatorTarget_Register, action: kCTMediatorActionNavigaTo_RegisterVC, params: params, shouldCacheTarget: false) as? XYJRegisterVC {
        
        return registerVc
    } else {
        // 这里处理异常场景,具体如何处理取决于产品
        return XYJBaseVC.init()
    }
    
}

}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.