美文网首页
iOS 组件化

iOS 组件化

作者: 114105lijia | 来源:发表于2021-01-05 16:20 被阅读0次

    在一个APP开发过程中,如果项目较小且团队人数较少,使用最基本的MVC、MVVM开发就已经足够了,因为维护成本比较低。但是当业务慢慢发展起来后,开发人员和代码量也都增多了。这时单一工程开发模式就会显露出一些弊端:

    • 耦合比较严重
    • 容易出现冲突
    • 业务方的开发效率不够高

    为了解决这些问题,就采取了「组件化」策略。它能带来这些好处

    • 加快编译速度
    • 自由选择开发姿势
    • 方便 QA 有针对性地测试
    • 提高业务开发效率

    所谓的组件化,就是把APP根据业务拆分为各独立的组件,各个组件相互协作,组成完整的APP。


    image.png

    组件化方案

    直接看demo

    1、url-block

    这是蘑菇街中使用的一种页面间调用的方式,通过在启动时注册组件提供的服务,把调用组件使用的 url 和组件提供的服务 block 对应起来,保存到内存中。在使用组件的服务时,通过 url 找到对应的 block,然后获取服务。

    url-block 的架构图: image.png

    每个组件都有一个 Entry,这个 Entry,主要做了三件事

    • 注册这个组件关心的 URL
    • 注册这个组件能够被调用的方法/属性
    • 在 App 生命周期的不同阶段做不同的响应
    使用姿势:

    注册:

    [MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {
            AAAViewController *vc = [AAAViewController new];
            UINavigationController *nav = [routerParameters[MGJRouterParameterUserInfo] objectForKey:@"nav"];
            vc.des = [routerParameters[MGJRouterParameterUserInfo] objectForKey:@"des"];
            vc.backBlock = [routerParameters[MGJRouterParameterUserInfo] objectForKey:@"block"];
            [nav pushViewController:vc animated:NO];
        }];
    

    调用:

    [MGJRouter openURL:@"mgj://detail?id=:id" withUserInfo:@{@"nav": self.navigationController, @"des": @"desTitle-A", @"block": ^(NSString *des){
                    NSLog(@"---des = %@",des);
                }} completion:nil];
    

    蘑菇街为了统一 iOS 和 Android 的平台差异性,专门用后台来管理 url,然后针对不同的平台生成不同类型的文件。

    使用 url-block 的方案的确可以组件间解耦,但是还是存在其它明显的问题,比如:

    • 需要在内存中维护 url-block 的表,组件多了可能会有内存问题;
    • url 的参数传递受到限制,只能传递常规的字符串参数,无法传递非常规参数,如 UIImage、NSData 等类型;
    • 没有区分本地调用和远程调用的情况,尤其是远程调用会因为 url 参数受限,导致一些功能受限;
    1、protocol-class

    针对方案 1 的问题,蘑菇街又提出了另一种组件化的方案,就是通过 protocol 定义服务接口,组件通过实现该接口来提供接口定义的服务,具体实现就是把 protocol 和 class 做一个映射,同时在内存中保存一张映射表,使用的时就通过 protocol 找到对应的 class 来获取需要的服务。

    protocol-class 的架构图: image.png

    注册:

    [ModuleManager registerClass:ClassA forProtocol:ProtocolA]
    

    调用:

    [ModuleManager classForProtocol:ProtocolA]
    

    蘑菇街的这种方案确实解决了方案 1 中无法传递非常规参数的问题,使得组件间的调用更为方便,但是它依然没有解决组件依赖中间件、内存中维护映射表、组件的分散调用的问题。设计思想和方案 1 类似,都是通过给组件加了一层 wrapper,然后给使用者调用。

    3、target-action

    target-action 的方案是通过给组件包装一层 wrapper 来给外界提供服务,然后调用者通过依赖中间件来使用服务;其中,中间件是通过 runtime 来调用组件的服务,是真正意义上的解耦,也是该方案最核心的地方。具体实施过程是给组件封装一层 target 对象来对外提供服务,不会对原来组件造成入侵;然后,通过实现中间件的 category 来提供服务给调用者,这样使用者只需要依赖中间件,而组件则不需要依赖中间件。

    target-action 的架构图: image.png

    action:

    @implementation Target_BModule
    
    - (BBBViewController *)Action_BBBVC:(NSDictionary *)para {
        BBBViewController *vc = [BBBViewController new];
        vc.des = para[@"des"];
        vc.backBlock = para[@"block"];
        return vc;
    }
    

    调用:

    UIViewController *vc = [[CTMediator sharedInstance] performTarget:Module_B action:Action_BBB params:@{@"des": @"desTitle-B", @"block": ^(NSString *des){
              NSLog(@"---des = %@",des);
         }} shouldCacheTarget:YES];
    [self.navigationController pushViewController:vc animated:NO];
    

    组件化优缺点

    优点
    1、组件之间相互独立。各组件开发成员之间的代码想相互独立编写的,独立编译,独立运行和独立测试的。
    2、资源的重复里用,尤其是功能性,工具性的代码,可以很轻松的重复里用
    3、迭代的效率提高。通过迭代进行功能的增减,只需要进行组件的拆分和组合。很方便也很高效

    缺点
    1、增加了代码的冗余,组件化颗粒度越细,中间代码越多
    2、增加了项目的复杂度,复杂度越高越容易出问题
    3、学习成本高,对于开发人员对各种工具的掌握要求也比较高,对于新手来说入门较为困难。
    4、由于工具和流程的复杂化,导致团队之间协作的成本变高,某些情况下可能会导致开发效率下降。

    但长远来看,组件化带来的好处是远远大于坏处的,特别是随着项目的规模增大,这种好处会变得越来越明显。

    最后,针对url-block方案和target-action方案写了一个demo。点我

    参考:
    https://www.cnblogs.com/dins/p/ios-zu-jian-hua-fang-an.html

    相关文章

      网友评论

          本文标题:iOS 组件化

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