ios 实现本地组件化+CTMediator解耦

2,775 阅读2分钟

概述

上篇文章cocopods创建私有库,主要讲解通过cocopods创建私有库。这篇文章主要讲解通过cocopods实现本地组件化,以及CTMediator的如何实现和实现原理

demo

下面创建了一个本地化的组件化的 demo,该demo没有实现具体的功能,知识创建了几个组件,仅供参考

CTMediator用法

比如上面的demo中有QHHomeModuleQHUserModule两个组件。现在需要这两个组件之间可以相互的使用,为了不出现耦合,我们可以使用CTMediator这个中间者来解耦。

没有解耦之前:

解耦之前.png 使用CTMediator解耦之后:

截屏2021-10-22 下午2.46.09.png

创建Target-Action

比如我们希望首页模块的功能被其他模块使用,需要创建一个Target_QHHomeModule,并且必须以Target_开头。

截屏2021-10-22 下午3.00.46.png

创建访问首页的实例方法必须以Action_开头

- (UIViewController *)Action_nativeHomeViewController:(NSDictionary * _Nonnull** )params{
    QHHomeViewController *vc = [[QHHomeViewController alloc] init];
    return* vc;
}

创建CTMediator Category

创建CTMediator+QHHomeModuleAction.h,添加分类方法

NSString * const kCTMediatorTargetHomeModule = @"QHHomeModule";
NSString * const kCTMediatorActionNativeHomeViewController = @"nativeHomeViewController";

- (UIViewController *)CTMediator_naviagetHomeVC:(NSDictionary *)parames{

    UIViewController *viewController = [self performTarget:kCTMediatorTargetHomeModule
       action:kCTMediatorActionNativeHomeViewController
                params:parames
                shouldCacheTarget:NO ];
    return viewController;
}

其中kCTMediatorTargetHomeModule定义的名字必须和上面Target_后面的名字匹配,kCTMediatorActionNativeHomeViewController定义的名字必须和Action_后面的名字匹配

CTMediator使用

如果需要使用首页模块只需要引入CTMediator+QHHomeModuleAction.h即可,然后调用下面的方法即可

UIViewController *vc =   [[CTMediator sharedInstance] CTMediator_naviagetHomeVC:@{}];

CTMediator源码分析

我们看CTMediator主要提供了4个接口

  • 单例获取
  • performActionWithUrl:远程App调用入口
  • performTarget:本地组件调用
  • releaseCachedTargetWithTargetName:释放 通过看源码我们发现其实performActionWithUrl,最终还是调用performTarget,所以我们主要分析一下performTarget方法即可

performTarget方法

  • 通过缓存获取Taget,如果换成没有,直接创建

截屏2021-10-22 下午3.45.39.png

  • 获取到对应的Tagetaction,如果有对应的实现调用safePerformAction

截屏2021-10-22 下午3.47.14.png

  • safePerformAction方法其实很简单,如果method的返回类型是id类型,这直接调用performSelector实现消息的发送,如果method的返回类型是voidNSIntegerBOOL类型通过NSInvocation来实现转发。

总结,CTMediator方法实际上就是通过OC语言的动态特性,通过字符串动态的获取到对应的类对象,让后通过消息的转发msg_send,动态的来实现方法的调用。