ios底层原理

iOS解耦合-你做到了吗?

2022-08-08  本文已影响0人  erlich

你经历的项目有多大,别人不敢想

一天的coding,你经历过多少次编译调试

xcode一天经历多少次crash

你的架构师卷你了没

你抱怨你的mac老旧了没


具体iOS解耦方面,看过同仁发布的一些博客,重在工具原理居多,但具体操作并未提及,讳莫如深

具体解耦执行阶段,编译层面问题,运行库符号问题上,我还未发现细丝入微的博文出现

当然,解耦方面也借助于工具,但工具是死的,在项目执行阶段,我们能做到什么样的程度,各有各的方法论

如果你有这方面的困惑,希望这篇文章能对你有帮助

一、解耦之路

  1. 小白单工程,什么都往里塞

  2. 模块化,一个变两个,两个变4个

    • 横向分层,业务层纵向梳理
    • 大家还是要凑在一个项目里维护自己的模块
    • 各自模块依赖主工程
    • 模块间的管理还是会发生冲突
  1. 插件化

    • Cocoa Pods/Maven
    • 模块剥离为独立工程,单独做版本管理
    • 隔离开团队/项目之间的相互依赖 彼此独立开发
    • ... 但是,但是还不能解决独立编译问题,依赖还是很严重
  2. 组件化

    • 解决独立编译、运行、调试
    • 独立插件不再是一稳定版本号,而是一个稳定的二进制包

从小白一路走来,未觉自己现在多高阶,只觉当初多无知无畏

1~4,不知会否共鸣作为开发者的你

  • 曾几何时,插件化之后自己一度感觉很满足
  • 但是,越往后来,源码越来越多,越来越烦,总看不惯别人的代码,一个最明显的感觉,慢,非常的慢,超级慢,上万个资源,Xcode索引就是个无底洞
  • 硬着头皮,无论如何要做切割,组件化独立编译,避无可避
  • 当下,你是否解决了组件化独立编译发布问题呢~~~

二、解决源码依赖,从物理上切断头文件依赖

最明显的一点,import 头文件引用,曾经还一度傻傻的在考虑预编译头文件问题

项目的过度耦合,很重要的一个原因就是通过声明头文件找到方法(函数)入口,少了头文件,编译不过

有3种方式可以依循


三、解耦工具「BeeHive」

BeeHive是基于接口Service的方式实现

BeeHive为模块编排事件,通过模块注册,模块调用可以实现模块的通信

可是组件独立编译问题依然没有解决

image.png

如果去掉各组件的外部依赖,问题变得相当简单,我们可以利用Home,Comm,Live各自的framework集成到主项目里,没有任何编译问题

但是,这样操作,我们的组件化将变得毫无意义,组件如果没有外部组件BeeHive,AFNetworking的依赖支持,源码间的依赖又成了问题,而且我们剥离的这个组件不再是业务模块组件

总之 这会使得我们的具体业务模块组件化变得毫无意义


四、千呼万唤始出来

BeeHive的详细原理介绍与具体使用不再此博客的讨论范畴

很明显,最终编译的组件依赖的三方组件存在于 设备 Debug-iphonesimulator 目录位置

说明:

直接集成 IFLHomeModule.framework BeeHive.framework 到主工程就可以了

你会在 .app里找到 业务组件最终的 二进制文件

有兴趣可以测下主工程编译时间,一定会大大出乎你的意料

🌟🌟所有的业务组件都是二进制,你自己的组件不再需要依赖工程源码环境进行编译调试,编译效率指数级改观

五、想当然了,依赖framework的import问题

目前的主工程状态:

组件化到这一步已经是一个不错的里程碑,除了,主工程里对组件的import依赖

是否可以解决,最起码我们期望后续的开发

只有确定无疑的结果才是可信的

这里需要解决两个问题

比如在主工程里 #import "IFLHomeModule/IFLBaseViewController.h"

我们要去除掉这行import,通过BeeHive实现对HomeModule组件的正常访问

你还得保障 组件framework embedin,即 general - Embedded Content - 组件库选择 Embed, 否则相应的组件里符号你找不到

由于你的组件 根 你的主工程都会依赖三方库,比如 都依赖 BeeHive

为了避免编译器逻辑冲突,避免组件的显示import


//#import "IFLHomeModule/Eservice.h"
//#import "BeeHive/Beehive.h"

- (void)enterHomeModule {
    Protocol *serviceProtocol = NSProtocolFromString(@"IFLMVVMServiceProtocol");
    NSLog(@"serviceProtocol = %@", serviceProtocol);
    if (!serviceProtocol) {
        NSLog(@"目标组件 - homeModule组件不存在..");
        return;
    }
    
//    id destVc = [[BeeHive shareInstance] createService:serviceProtocol];
    Class _BeeHive = NSClassFromString(@"BeeHive");
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
    if ([_BeeHive respondsToSelector:@selector(shareInstance)]) {
        id _BeeHiveInstance = [_BeeHive performSelector:@selector(shareInstance)];
        if ([_BeeHiveInstance respondsToSelector:@selector(createService:)]) {
            id destVc = [_BeeHiveInstance performSelector:@selector(createService:) withObject:serviceProtocol];
            
            if ([destVc isKindOfClass:[UIViewController class]]) {
                [self presentViewController:destVc animated:YES completion:^{

                }];
            }
        }
    }
#pragma clang diagnostic pop
}

此时,如果移除组件,工程没有影响,只是进入组件入口就此中断了

参考项目 ModuleImpl

上一篇下一篇

猜你喜欢

热点阅读