一、简介
CCRouter 是一个简单的iOS项目页面URL路由组件。它旨在使项目中处理复杂跳转变得简单。
CCRouter 可以很方便的处理不同 URL schemes 以及解析它们的参数,并通过回调 block 来处理 URL 对应的操作 , 是一个可以用于处理复杂跳转逻辑的三方库。
二、使用场景
1、在日常开发中,push、present 出现在整个程序的各个地方,如果你想快速理清一个项目的整体逻辑,那会非常麻烦。大多数情况 , 你得找到代码目录,根据层级结构分出关系,然后找到对应的push位置,寻找下一级页面,如果本身项目的目录就非常乱,那么如果要了解一个项目的整体跳转逻辑,将会更加困难。
如果能把整个项目的跳转逻辑都给抽取出来,单独放在一个类,模块化管理,那么思路就会清晰很多,甚至可以用 XMind 根据代码画出整个项目的树状图。
2、如果所处公司存在多个app,app之间互相推荐互相跳转是再正常不过的需求,就类似于QQ、微信、第三方分享跳转等。如果用Appdelegate 原生方法进行拦截,所做的事至少得是判断 Scheme 是否匹配,想办法进入需要跳到的界面,如果要涉及传参,就更加麻烦。
3、如果用户是从 PC端 识别二维码,或者通过链接想要进入 app 指定页面。
三、原理
本质
CCRouter 本质可以理解为:保存一个全局的字典,key 是 URL,value 是对应存放 block 的数组,URL 和 block 都会常驻在内存中,当打开一个 URL 时,CCRouter 就可以遍历这个全局的字典,通过 URL 来执行对应的 block。
- (void)registerBlock:(void (^)(NSDictionary * _Nonnull))routeHandleBlock forRoute:(NSString *)route {
if (routeHandleBlock && route.length > 0) {
[self.routes addObject:route];
[self.blocksByRoute setObject:[routeHandleBlock copy] forKey:route];
}
}
参数的解析
/**
例如iOS://tasklist?title=任务列表&code=12
*/
- (CCRouterInfo *)routeInfo:(NSString *)fullRoute {
CCRouterInfo *info = [[CCRouterInfo alloc] init];
NSArray *fullParts = [fullRoute componentsSeparatedByString:@"://"];
if (fullParts.count < 2) {
return nil;
}
info.scheme = [fullParts firstObject];
NSString *delimiter = @"?";
NSArray *routePartArray = [fullRoute componentsSeparatedByString:delimiter];
info.routePath = [routePartArray firstObject];
if (routePartArray.count == 1) {
info.routeParameter = @{};
return info;
}
NSAssert(routePartArray.count > 1, @"带参Route必须包含“?”右侧参数");
NSString *paramsString = [routePartArray objectAtIndex:1];
delimiter = @"&";
NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary];
NSArray *paramsPartArray = [paramsString componentsSeparatedByString:delimiter];
delimiter = @"=";
for (NSString *keyAndValue in paramsPartArray) {
NSArray *keyValueArray = [keyAndValue componentsSeparatedByString:delimiter];
NSAssert(keyValueArray.count == 2, @"参数key和value都不能为空");
NSString *key = [keyValueArray firstObject];
NSString *value = [keyValueArray lastObject];
[paramsDict setObject:value forKey:key];
}
info.routeParameter = paramsDict;
return info;
}
四、用法
1、pod 引入
pod 'CCRouter'
2、 注册
URL带参注册方式
[[CCRouter sharedInstance] registerBlock:^(NSDictionary *param) {
FirstViewController *firstVC = [[FirstViewController alloc] init];
firstVC.strTitle = param[@"title"];
firstVC.strTips = param[@"tips"];
UINavigationController *navc = [UIViewController currentViewController].navigationController;
[navc pushViewController:firstVC animated:YES];
} forRoute:@"ios://firstpage"];
单独传递参数注册方式
[[CCRouter sharedInstance] registerDictionaryParamBlock:^(NSDictionary *params) {
SecondViewController *secondVC = [[SecondViewController alloc] init];
secondVC.strTitle = params[@"title"];
secondVC.strTips = params[@"tips"];
UINavigationController *navc = [UIViewController currentViewController].navigationController;
[navc pushViewController:secondVC animated:YES];
} forRoute:@"ios://secondpage"];
3、调用
URL带参调用方式
[[CCRouter sharedInstance] handleRoute:@"ios://firstpage?title=url带参&tips=这是第二个参数"];
单独传递参数调用方式
NSDictionary *dict = @{
@"title":@"参数传递",
@"tips":@"这是第二个参数"
};
[[CCRouter sharedInstance] handleRoute:@"ios://secondpage" parameter:dict];
支持iOS、H5、Flutter页面及外部APP的跳转
按照规定的URL规则(schame://xxx/xx?key1=value1&key2=value2)
schame:
用来标识跳转的页面是iOS/H5/Flutter还是外部APP
- (BOOL)isDingTalkRouter:(NSString *)route {
return [route hasPrefix:@"dingtalk"];
}
//是APP的本地页面
- (BOOL)isiOSRoute:(NSString *)route {
return [route hasPrefix:@"iOS:"];
}
- (BOOL)isWebRoute:(NSString*)route {
if ([route hasPrefix:@"http"]) {
return YES;
} else {
return NO;
}
}
- (BOOL)isFlutterRoute:(NSString *)route {
return [route hasPrefix:@"flutter"];
}
GitHub地址