我个人理解下iOS蘑菇街组件化的实现方式
随着业务需求的增长,越来越多的业务线部门及开发者会参与到项目的实现中来,单应用结构就开始不能满足并行高效率的开发需求了。组件化的开发模式解决了上述问题,成为了大部分公司的项目实现方式。
什么是组件化,先看下面的图:
引用casatwy老师的一句话:中间件对组件产生了依赖的话,其他模块也需要耦合中间层才能发起调用。这样还是存在之前的相互耦合的问题,而且本质上比之前更麻烦了。
双向依赖就像我们在项目中把页面跳转集中到一个中间类中。在页面内引动中间类来实现跳转,随着页面的增多与跳转逻辑变得越来越复杂,我们会发现中间类并不会起到解耦合的作用,跳转逻辑还是会变得越来越复杂。所以必须实现组件对中间件的单向依赖。
蘑菇街一开始是使用的openURL
的方式,具体是使用MGJRouter进行URL的注册跳转,使用方式如下:
//注册详情页
[MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {
NSNumber *id = routerParameters[@"id"];
// create view controller with id
// push view controller
}];
//调用详情页
[MGJRouter openURL:@"mgj://detail?id=404"];
其中MGJRoute
还有一个方法:
+ (void)openURL:(NSString *)URL withUserInfo:(NSDictionary *)userInfo completion:(void (^)(id result))completion
上面的方法是为了实现传递非字符串可描述的参数,需要把非字符串可描述参数通过userInfo来传递。
但是这就需要对每个组件的URL和调用参数有一个地方来进行记录和管理。后来蘑菇街为了解决这个问题,建立了通过从后台获取URL的方式来管理URL列表,虽然这带来了URL管理的便利,但是带来的问题是非字符串可描述参数无法在管理后台配置,openURL
的方式大打折扣。
然后为了组件间调用传递非字符串可描述参数,蘑菇街实施了第二种组件调用方式URLProtocol
,主要涉及类ModuleManager
和PublicProtocols
,ModuleManager
主要函数如下:
@protocol ModuleProtocol <NSObject>
//APP生命周期相关代理分发
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
//省略若干
@end
@interface ModuleManager : NSObject
//获取远程配置的组件URLs
+ (instancetype)instance;
- (void)loadModuleFromPlist:(NSString *)plistPath;
- (NSArray *)allModules;
//注册组件协议及关联类
+ (void)registerClass:(Class)xClass forProtocol:(Protocol *)protocol;
+ (Class)classForProtocol:(Protocol *)protocol;
@end
至于PublicProtocols
类,主要是各组件需注册的Protocol的声明。个人感觉,这其实跟OpenURL
的本质上是一样的。PublicProtocols
中各组件注册Protocol的声明,然后在ModuleManager
注册的过程跟注册URL方式是一样的。URLProtocol
的实现方式是为了实现非字符串可描述参数的传递,个人觉得这种方式要比OpenURL
方式更直观一些。我写了一个URLProtocol
方式的Demo,地址如下:蘑菇街Protocol方式Demo,里面简单实现了Protocol的注册跟调用,大家可以参考下。
如果我的文章对你有所帮助,请留言告诉我,Thanks!
推荐阅读