iOS 组件间方案 -- MGJRouter& CTMediator

人生"码农"无闲暇,忙里偷闲得几回。最近在思考项目项目组件化的问题,重翻了前段时间iOS圈关于组件化的讨论,这里做下梳理和自己的总结。

说到组件化的技术方案,最早是Limboy分享了一篇蘑菇街组件化的技术方案,接着Casa提出了不同意见,后来Limboy在Casa反馈之上对自己方案做了进一步优化,最后Bang在前三篇文章基础之上做了清晰的梳理总结。通读之后,获益颇多,现总结如下:

1672235-97278b0840782d7b.png
组件001.png
一、MGJRouter的简单使用

蘑菇街团队提供了MGJRouter路由库,使用比较简单,其原理主要是通过注册URL来实现路由跳转。主要有两个步骤:
① 注册URL生成路由表
② openUrl实现跳转

应用场景:
1.vc之间的跳转(传值/反向传值)
核心代码如下:
(1).注册URL
NS_ASSUME_NONNULL_BEGIN

@interface RouterManager : NSObject

@end

NS_ASSUME_NONNULL_END

#import "RouterManager.h"
#import <MGJRouter.h>
#import "TestOneViewController.h"
#import "TestTwoViewController.h"

@implementation RouterManager

+(void)load {
 
    [MGJRouter registerURLPattern:@"mgj://loadFirstViewController" toHandler:^(NSDictionary *routerParameters) {
        BaseNavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        FirstViewController *vc = [[FirstViewController alloc] init];
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    
    [MGJRouter registerURLPattern:@"mgj://loadSecondViewController" toHandler:^(NSDictionary *routerParameters) {
        UINavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        NSString *labelText = routerParameters[MGJRouterParameterUserInfo][@"text"];
        SecondViewController *vc = [[SecondViewController alloc] init];
        vc.labelText = labelText;
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    
    [MGJRouter registerURLPattern:@"mgj://loadThirdViewController" toHandler:^(NSDictionary *routerParameters) {
        UINavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        void(^block)(NSString *) = routerParameters[MGJRouterParameterUserInfo][@"block"];
        ThirdViewController *vc = [[ThirdViewController alloc] init];
        vc.clicked = block;
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    [MGJRouter registerURLPattern:@"mgj://loadFourthViewController" toObjectHandler:^id(NSDictionary *routerParameters) {
        NSString *labelText = routerParameters[MGJRouterParameterUserInfo][@"text"];
        FourthViewController *vc = [[FourthViewController alloc] init];
        vc.labelText = labelText;
        return vc;
    }];
    
}
@end

(2).调用url
- (IBAction)firstClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadFirstViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController}
            completion:nil];
}

- (IBAction)secondClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadSecondViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController,
                         @"text": @"我喜欢出发"
                        }
            completion:nil];
}


- (IBAction)thirdClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadThirdViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController,
                         @"block":^(NSString * text){
        NSLog(@"%@",text);
    },
                       }
            completion:nil];
}

- (IBAction)fourClick:(UIButton *)sender {
    NSString *textStr = @"模拟器32位处理器测试需要i386架构,模拟器64位处理器测试需要x86_64架构,真机32位处理器需要armv7,或者armv7s架构,真机64位处理器需要arm64架构";
      [self.navigationController pushViewController:[MGJRouter objectForURL:@"mgj://loadFourthViewController" withUserInfo:@{@"text" : textStr}] animated:YES];
}

可打印看下routerParameters字典的内容:

{
    MGJRouterParameterCompletion = "<__NSGlobalBlock__: 0x10cae0208>";
    MGJRouterParameterURL = "mgj://loadTestOneViewController";
    MGJRouterParameterUserInfo =     {
        navigationVC = "<BaseNavigationController: 0x7f9e6501f400>";
    };
}

MGJRouter的简单使用就是这样,但是看这里不知道大家是否和我一样,有个疑惑,程序运行load方法会自动执行,为什么要在load方法里面写呢,接着往下看。。。

2. MGJRouter的弊端

① 每个业务组件,都需要一来这个MGJRouter框架
② URL维护成本高(url字符串写错,则不执行操作)
基于MGJRouter有以上弊端,这里引入Target-action方案,采用的是 CTMediator 这套方案.

1672235-8d6c8f392f4c88a8.png
target-action.png
target-action方案原理:
  • 每个组件, 提供一个统一披露的接口文件
  • 额外的维护一个中间件的分类扩展(在此处进行硬解码 通过运行时进行物理解耦)
  • 其他地方通过target-action;的方案进行交互

这里如何把模块做成私有pods就不过多介绍了,我这里就简单介绍下 CTMediator 库 但是用方法,没有按照标准的私有库结构去创建工程,具体可参考Target-Action方案主工程 Demo中的工程结构,这个是标准的组件库目录.
步骤:
(1).在项目中导入/pod 下CTMediator
(2).创建CTMediator+JumpToolsTarget_ClassController类,具体代码见下图:

1672235-e9d7c4299900eda2.png
code.png

我们再看下Target_ClassController类里面的代码,如图:

1672235-d4b8b2b5c6fbbf48.png
code2.png

注意:

CTMediator+JumpTools类中[self performTarget:<#(NSString *)#> action:<#(NSString *)#> params:<#(NSDictionary *)#> shouldCacheTarget:<#(BOOL)#>]; 这个方法Targetaction的字符串不是随便填写的,是按照一定的规则来的,而且Target_ClassController类名字一定要以Target_XXXX来开头,而且Target_XXXX里面的方法,也一定要以-(void)Action_为开头,具体原因是因为Casa大佬的这个CTMediator库,里面的performTarget方法就是以Target_Action_开头的,具体实现原理可以看CTMediator库源码中的实现, 当然你也可以修改Casa大佬的库的源码,也就一个类,但是如果你是pod到项目中的方式,不建议修改,就按照这种规则创建类名以及方法名即可。

Demo下载地址.

再强调下,这里我这个CTMediator的Demo,不是按照标准的组件库的形式来举例子的,只是介绍下CTMediator库的用法,具体可参考Target-Action方案主工程 Demo中的工程结构,这个是标准的组件库目录.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值