上一篇中介绍了项目解耦中的构建Spec私有库,这篇记录一下本次模块化之路的另一个重要环节,构建路由。
路由,可以理解为一个模块的调度中心。我们写项目时,经常有业务模块与业务模块、业务模块与功能模块之间的相互调用,如果在使用的时候直接引用,做模块间的随意跳转,这样会产生很多耦合与依赖,而我们构建路由的目的,就是要去掉这些耦合,做到模块间互不依赖,不相影响。
先看看目前项目的路由构建:
下面开始一步一步地构建路由
一、路由注册
// 路由的发起
+ (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options {
if ([url.absoluteString containsString:kOrderApplicationScheme]){
return [[JLRoutes routesForScheme:kOrderApplicationScheme] routeURL:url];
}
return NO;
}
// 路由的注册
+ (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[JLRoutes routesForScheme:kOrderApplicationScheme] addRoute:@"order/puchase" handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
LBOrderWorkbenchPageViewController *vc= [[LBOrderWorkbenchPageViewController alloc] init];
[[UIApplication getCurrentViewController].navigationController pushViewController:vc animated:YES];
return YES;
}];
[[JLRoutes routesForScheme:kOrderApplicationScheme] addRoute:@"order/supply" handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
LBSupplyWorkbenchPageViewController *vc= [[LBSupplyWorkbenchPageViewController alloc] init];
[[UIApplication getCurrentViewController].navigationController pushViewController:vc animated:YES];
return YES;
}];
return NO;
}
二、路由的发起
#define LBOrderOpen(n) NSString *url = [kOrderApplicationScheme stringByAppendingString:n];\
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:url]];\
case 1:
{
// 采购
LBOrderOpen(@"order/puchase");
}
break;
case 5:
{
// 供应
LBOrderOpen(@"order/supply");
}
break;
三、中心调度
在项目的AppDelegate里面进行设置注册与发起路由之后的调度
// 设置注册
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[LBBeeApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBUserApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBHomeApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBPayApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBResourceApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBShareApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBUnionNumberApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBRecruitApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBMessageApplicationLifeCycle application:application didFinishLaunchingWithOptions:launchOptions];
[LBOrderApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBCategoryApplication application:application didFinishLaunchingWithOptions:launchOptions];
[LBTenderApplication application:application didFinishLaunchingWithOptions:launchOptions];
...
return YES;
}
// 中心调度
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options{
BOOL result;
result = [LBUserApplication application:app openURL:url options:options];
result = result ? :[LBBeeApplication application:app openURL:url options:options];
result = result ? :[LBResourceApplication application:app openURL:url options:options];
result = result ? :[LBShareApplication application:app openURL:url options:options];
result = result ? :[LBUnionNumberApplication application:app openURL:url options:options];
result = result ? :[LBOrderApplication application:app openURL:url options:options];
result = result ? :[LBRecruitApplication application:app openURL:url options:options];
result = result ? :[LBCategoryApplication application:app openURL:url options:options];
result = result ? :[LBTenderApplication application:app openURL:url options:options];
result = result ? :[LBHomeApplication application:app openURL:url options:options];
result = result ? :[LBPayApplication application:app openURL:url options:options];
if (!result) {
// url没人处理,则处理其他非业务模块的url
}
return result;
}
四、传参与回调
我们在做路由的时候,经常会碰到需要传值与返参的操作:
- 入参
LBOrderOpen(@"order/puchase/1001/5001");
[[JLRoutes routesForScheme:kOrderApplicationScheme] addRoute:@"order/puchase/:bsId/:bsCode" handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
LBOrderWorkbenchPageViewController *vc= [[LBOrderWorkbenchPageViewController alloc] init];
vc.bsId = parameters[@"bsId"];
vc.bsCode = parameters[@"bsCode"];
[[UIApplication getCurrentViewController].navigationController pushViewController:vc animated:YES];
return YES;
}];
- 回调
[LBCategoryApplication openURL:@"category/selected/5/1/0" callBack:^(NSArray<NSDictionary *> *resultArray) {
}];
我们做路由的时候常常会使用到回调,这里我们可以JLRoutes添加分类,新增路由对block的带入与引用。
// addBlock
+ (void)openURL:(NSString *)urlStr callBack:(LBRouteCallBackBlock)callBack
{
NSString *blockAdd = [JLRoutes addCallBackBlock:callBack];
urlStr = [urlStr stringByAppendingString:[NSString stringWithFormat:@"/%@",blockAdd]];
LBCategoryOpen(urlStr);
}
// getBlock
LBRouteCallBackBlock callBlock = [JLRoutes getCallBackWithKey:blockKey];
这里的addCallBackBlock与getCallBackWithKey其实是以单例的形式,将block的%p作为键值的key保存起来,再以%p作为路由的参数之一作为url传送;反之get方法是将单例中的键值以key来获取,从而获取到block。这里介绍的是一种思路,当然还有有更好的思路去做这件事,我们可以进行再探讨,毕竟任何项目的构建都会不断的在完善。
注:
- 模块间所有供外部使用的功能和页面,都应该制作成路由
- 依赖关系是路由中需要重点考虑的,写代码时降低耦合性,可以使项目间的调度变得清晰
- 路由集成的思想可以仿照写SDK,比如一个公司有几个app,写一个支付中心或者是消息IM推送中心,它可以无条件的使用在不用的app当中
- 集成路由的前提还是模块化完成,将组件写成Spec私有库就是模块化前有效的工作
end