什么是組件化晾匠?
打個(gè)比方,一臺(tái)電腦由CPU梯刚、內(nèi)存凉馆、硬盤(pán)等組件組成,他們拆卸下來(lái)之后放在其他地方也是可以使用的亡资,且CPU與硬盤(pán)之間是沒(méi)有任何聯(lián)系的澜共。
為什么要組件化?
而代碼在慢慢堆積起來(lái)之后锥腻,許多類(lèi)之間都存在著“你離不開(kāi)我嗦董,我離不開(kāi)你”的情況,這就會(huì)導(dǎo)致開(kāi)發(fā)效率低下瘦黑,且容易造成代碼沖突京革。其實(shí)說(shuō)白了就是耦合度太高。這樣揉成一坨對(duì)測(cè)試/編譯/開(kāi)發(fā)效率/后續(xù)擴(kuò)展都有一些壞處
「組件化」顧名思義就是把一個(gè)大的 App 拆成一個(gè)個(gè)小的組件匹摇,相互之間不直接引用。那如何做呢甲葬?
實(shí)現(xiàn)方式
照理想設(shè)計(jì)圖所示,Mediator作為一個(gè)中間件起著調(diào)度各個(gè)模塊的作用演顾,那么Mediator 怎么去轉(zhuǎn)發(fā)組件間調(diào)用供搀?
本文將以 JLRoutes 作為Mediator。
在使用JLRoutes之前钠至,請(qǐng)配置scheme葛虐,詳見(jiàn)
http://blog.csdn.net/u010127917/article/details/50451251
JLRoutes本質(zhì)可以理解為:保存一個(gè)全局的Map,key是url棉钧,value是對(duì)應(yīng)的block屿脐。這樣在下面的代碼中:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [JLRoutes routeURL:url];
}
如果自己被打開(kāi):
NSURL *viewUserURL = [NSURL URLWithString:@"myapp://user/view/joeldev"];
[[UIApplication sharedApplication] openURL:viewUserURL];
JLRoutes就可以遍歷這個(gè)全局的map,通過(guò)url來(lái)執(zhí)行對(duì)應(yīng)的block。
廢話不多說(shuō)的诵,直接上代碼吧万栅!
appdelegate中設(shè)置好匹配規(guī)則
然后根據(jù)傳遞過(guò)來(lái)的參數(shù)進(jìn)行跳轉(zhuǎn)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// navigationPush規(guī)則
[JLRoutes addRoute:@"/NaviPush/:controller" handler:^BOOL(NSDictionary<NSString *,NSString *> * _Nonnull parameters) {
// 獲取當(dāng)前控制器
UIViewController *currentVc = [self currentViewController];
UIViewController *v = [[NSClassFromString(parameters[@"controller"]) alloc] init];
[self paramToVc:v param:parameters];
currentVc.hidesBottomBarWhenPushed = YES;
[currentVc.navigationController pushViewController:v animated:YES];
currentVc.hidesBottomBarWhenPushed = NO;
return YES;
}];
// StoryBoardPush規(guī)則
[JLRoutes addRoute:@"/StoryBoardPush" handler:^BOOL(NSDictionary<NSString *,NSString *> * _Nonnull parameters) {
// 獲取當(dāng)前控制器
UIViewController *currentVc = [self currentViewController];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:parameters[@"sbname"] bundle:nil];
UIViewController *v = [storyboard instantiateViewControllerWithIdentifier:parameters[@"bundleid"]];
[self paramToVc:v param:parameters];
currentVc.hidesBottomBarWhenPushed = YES;
[currentVc.navigationController pushViewController:v animated:YES];
currentVc.hidesBottomBarWhenPushed = NO;
return YES;
}];
return YES;
}
其實(shí)在這個(gè)環(huán)境下不引用任何需要跳轉(zhuǎn)的控制器來(lái)進(jìn)行參數(shù)傳遞是個(gè)麻煩的問(wèn)題,
所以使用runtime來(lái)進(jìn)行參數(shù)的傳遞
-(void)paramToVc:(UIViewController *) v param:(NSDictionary<NSString *,NSString *> *)parameters{
// runtime將參數(shù)傳遞至需要跳轉(zhuǎn)的控制器
unsigned int outCount = 0;
objc_property_t * properties = class_copyPropertyList(v.class , &outCount);
for (int i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *key = [NSString stringWithUTF8String:property_getName(property)];
NSString *param = parameters[key];
if (param != nil) {
[v setValue:param forKey:key];
}
}
}
控制器發(fā)送跳轉(zhuǎn)規(guī)則及參數(shù)
-(void)btnClick:(UIButton *) sender{
if (sender.tag == 0) {
NSString *customURL = @"TESTDEMO://NaviPush/SecondViewController?userId=99999&age=18";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
}else{
NSString *customURL = @"TESTDEMO://StoryBoardPush?sbname=Main&bundleid=SBVC";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
}
}
干貨來(lái)了N靼獭7沉!!
https://github.com/sthyuhao/JLRDemo