美文网首页
【Toki组件化】通信中间件 TKModule

【Toki组件化】通信中间件 TKModule

作者: TokiHunter | 来源:发表于2021-03-29 15:43 被阅读0次

    一、介绍

    组件化这件事,简单理解就是把不同的业务拆分成单独的项目去开发,组件之间可以出现引用关系,但不可以出现依赖关系。

    由于组件是不可以依赖另一个组件的,这导致调用其他组件的对外接口成为了一件很麻烦的事,传统方案是使用字符串映射Selector,这种方案依赖字符串这个不稳定的Key,不但没有代码联想,还会导致很多难以预测的问题。
    经过一些尝试,我发现了还有一种简单的方案。TKModule作为组件的中间件,各组件可以通过创建TKModule的分类实现对外接口,也通过TKModule去调用其他组件的对外接口

    当然,这也会带来一些问题:

    1. 我在开发A组件的时候,不能依赖B组件,那么我的开发环境中就不存在B组件的对外接口,就没法去调用。
    • 解决方案:组件间不可以依赖,但是可以引用。如果B组件的对外接口已经声明、实现并发布,我可以在A组件的Demo的Podfile添加B组件。
    1. 我在开发A组件的时候,C组件的对外接口仅仅作出声明,尚未实现便发布了,这时在A组件中调用C组件的对外接口 便会导致崩溃。
    • 解决方案: 在TKModule替换
      - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector;
      - (void)forwardInvocation:(NSInvocation *)invocation;
      的实现,使用户(组件使用者)调用未实现的接口时会执行一个空的实现,避免崩溃。
      此外,我也可以在A组件的Demo中,根据我的需要去实现这个接口。
    1. 我在开发A组件的时候,D组件尚发布,这时在A组件中如何调用D组件的接口。
    • 解决方案:遇到种情况我们可以在A组件中去声明想要引用的接口。

    二、基础用法

    • 实现接口

    //  TKModule+Account.h
    //  TKMAccountModule
    
    @interface TKModule (Account)
    
    - (void)showLoginView;
    
    @end
    
    //  TKModule+Account.m
    //  TKMAccountModule
    
    @implementation TKModule (Account)
    
    - (void)showLoginView {
        //展示登录界面
    }
    
    • 调用接口

    //  TKMInitializeEntrance.m
    //  TKMInitializeModule
    
    #import "TKMInitializeEntrance.h"
    
    @implementation TKMInitializeEntrance
    
    ...
    
    - (void)loginButtonTapped {    
        [[TKModule shared] showLoginView];
    }
    
    ...
    
    @end
    

    三、补充用法

    • 在组件中声明其他组件的对外接口

    //  TKModule+AccountRecharge.h
    //  TKMAccountModule
    
    #import "TKModule.h"
    
    @interface TKModule (AccountRecharge)
    
    - (void)showRechargeView;
    
    @end
    
    • 在Demo中实现其他组件的对外接口

    //  TKModule+Mock.m
    //  TKMAccountModule-Example
    
    #import <TKModule/TKModule.h>
    
    @implementation TKModule (Mock)
    
    - (void)showRechargeView {
        //展示充值页面
    }
    
    @end
    
    

    四、代码

    TKModule 地址

    //  TKModule.h
    
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    typedef void(^TKModuleUnrecognizedSelectorCallback)(SEL);
    
    @interface TKModule : NSObject
    
    @property (nonatomic, strong) TKModuleUnrecognizedSelectorCallback unrecognizedSelectorCallback;
    
    + (instancetype)shared;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    //  TKModule.m
    
    #import "TKModule.h"
    
    #import <objc/runtime.h>
    
    @implementation TKModule
    
    #pragma mark - shared
    
    + (instancetype)shared {
        static id instance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
        });
        return instance;
    }
    
    #pragma mark - Unrecognized
    
    - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
        NSMethodSignature *signature = [super methodSignatureForSelector:selector];
        if (!signature) {
            if (self.unrecognizedSelectorCallback) self.unrecognizedSelectorCallback(selector);
            signature = self.voidSignature;
        }
        return signature;
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        if (![invocation.methodSignature isEqual:self.voidSignature]) {
            [super forwardInvocation:invocation];
        }
    }
    
    #pragma mark - util
    
    - (NSMethodSignature *)voidSignature {
        return [self methodSignatureForSelector:@selector(unrecognizedSelectorBackUp)];
    }
    
    - (void)unrecognizedSelectorBackUp {
        
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:【Toki组件化】通信中间件 TKModule

          本文链接:https://www.haomeiwen.com/subject/sajfhltx.html