趁著這段項(xiàng)目空閑期听诸,把項(xiàng)目中用到的組件化方案記錄一下桅狠,免得遺忘。
簡(jiǎn)介
組件化是為了各個(gè)模塊不直接調(diào)用趴荸,降低耦合度儒溉,都是通過中間件來實(shí)現(xiàn)的,草圖如下
三種方案如下
1.蘑菇街URL路由方案
2.Target-Action方案
3.procotol-class方案
蘑菇街URL路由方案
URL路由方案參考的是蘑菇街MGJRouter方案
蘑菇街 App 的組件化之路
Target-Action方案
這個(gè)方案是根據(jù)casa大神的CTMediator的組件修改的发钝,稍微修改下調(diào)用方法睁搭,和當(dāng)前項(xiàng)目跟切合
- (id)performTargetName:(NSString *)targetName actionName:(NSString *)actionName param:(NSDictionary *)dicParam;
可以在每個(gè)模塊對(duì)中間件加一個(gè)category,這樣通過調(diào)用category方法,來降低耦合度笼平,這是category的實(shí)現(xiàn)方法
static NSString *const kBookTarget = @"BookTarget";
static NSString *const kBookAction = @"bookVCWithParam";
@implementation SYMediator (BookVC)
- (UIViewController *)bookViewControllerWithDicParam:(NSDictionary *)dicParm
{
UIViewController *vc = [self performTargetName:kBookTarget actionName:kBookAction param:dicParm];
if ([vc isKindOfClass:[UIViewController class]]) {
return vc;
} else {
return [[UIViewController alloc] init];
}
}
當(dāng)然也不可以增加category园骆,也可以實(shí)現(xiàn)。
NSDictionary *dicParm = @{@"bookName" : @"降龍十八掌",@"bookid" : @"sy0001"};
//第一種方式(有category)
UIViewController *bookVC = [[SYMediator shareInstance] bookViewControllerWithDicParam:dicParm];
[self.navigationController pushViewController:bookVC animated:YES];
//第二種方式 其實(shí)不對(duì)SYMediator 增加Category也是可以實(shí)現(xiàn)的寓调,就是代碼比較惡心而已 下面就是例子
// UIViewController *bookVC2 = [[SYMediator shareInstance] performTargetName:@"BookTarget" actionName:@"bookVCWithParam" param:dicParm];
// [self.navigationController pushViewController:bookVC2 animated:YES];
bang
大神的總結(jié) 組件通過中間件通信锌唾,中間件通過 runtime 接口解耦,通過 target-action 簡(jiǎn)化寫法夺英,通過 category 感官上分離組件接口代碼
procotol-class方案
這種方案是蘑菇街為了補(bǔ)全本地調(diào)用的功能晌涕,為組件多加了另一種方案,就是通過 protocol-class 注冊(cè)表的方式
還是通過一個(gè)中間件來實(shí)現(xiàn)的
- (void)registerProtocol:(Protocol *)protocl forClass:(id)provide;
- (id)classForProtol:(Protocol *)protocol;
具體實(shí)現(xiàn)就是把procotol
和class
做一個(gè)映射痛悯,同時(shí)在內(nèi)存中保存一張映射表余黎,使用的時(shí)候,就通過protocol
找到對(duì)應(yīng)的class來獲取需要的服務(wù)
- (void)registerProtocol:(Protocol *)protocl forClass:(id)provide
{
if (!protocl || !provide) {
return;
}
NSString *protocolName = NSStringFromProtocol(protocl);
[self.protocolCache setObject:provide forKey:protocolName];
}
- (id)classForProtol:(Protocol *)protocol
{
if (!protocol) {
return nil;
}
return self.protocolCache[NSStringFromProtocol(protocol)];
}
在每個(gè)模塊內(nèi)定義一個(gè)公共Procotol文件载萌,定義對(duì)外的接口
//ProtocolBookProtocol.h
@protocol ProtocolBookProtocol <NSObject>
- (UIViewController *)bookVCWithParam:(NSDictionary *)dicParm;
@end
最后在模塊里實(shí)現(xiàn)這些接口
// procotol-class 方案 有點(diǎn)繞 這個(gè)方案跟剛才兩個(gè)最大的不同就是惧财,它不是直接通過 Mediator 調(diào)用組件方法,而是通過 Mediator 拿到組件對(duì)象扭仁,再自行去調(diào)用組件方法
NSDictionary *dicParm = @{@"bookName" : @"降龍十八掌",@"bookid" : @"sy0001"};
//1.拿到組件對(duì)象
id<ProtocolBookProtocol> protocolBookManager = [[ProcotolManagerTool shareInstance] classForProtol:@protocol(ProtocolBookProtocol)];
//2.通過組件對(duì)象 再傳值
UIViewController *bookVC = [protocolBookManager bookVCWithParam:dicParm];
[self.navigationController pushViewController:bookVC animated:YES];
demo
參考鏈接:
iOS 組件化方案探索
蘑菇街 App 的組件化之路
iOS應(yīng)用架構(gòu)談 組件化方案