CocoaPods trunk is moving to be read-only. Read more on the blog, there are 18 months to go.
TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Aug 2017 |
Maintained by kingly09.
一个高效,灵活,易用 的 iOS URL Router
随着用户的需求越来越多,对App的用户体验也变的要求越来越高。为了更好的应对各种需求,开发人员从软件工程的角度,将App架构由原来简单的MVC变成MVVM,VIPER等复杂架构。更换适合业务的架构,是为了后期能更好的维护项目。
但是用户依旧不满意,继续对开发人员提出了更多更高的要求,不仅需要高质量的用户体验,还要求快速迭代,最好一天出一个新功能,而且用户还要求不更新就能体验到新功能。为了满足用户需求,于是开发人员就用H5,ReactNative,Weex等技术对已有的项目进行改造。项目架构也变得更加的复杂,纵向的会进行分层,网络层,UI层,数据持久层。每一层横向的也会根据业务进行组件化。尽管这样做了以后会让开发更加有效率,更加好维护,但是如何解耦各层,解耦各个界面和各个组件,降低各个组件之间的耦合度,如何能让整个系统不管多么复杂的情况下都能保持“高内聚,低耦合”的特点?这一系列的问题都摆在开发人员面前,亟待解决。
比如微信的3D-Touch可以直接跳转到“我的二维码”。“我的二维码”界面在我的里面的第三级界面。或者再极端一点,产品需求给了更加变态的需求,要求跳转到App内部第十层的界面,怎么处理?
如果自己App有几个,相互之间还想相互跳转,怎么处理?
随着项目越来越复杂,各个组件,各个页面之间的跳转逻辑关联性越来越多,如何能优雅的解除各个组件和页面之间的耦合性?
项目里面某些模块会混合ReactNative,Weex,H5界面,这些界面还会调用Native的界面,以及Native的组件。那么,如何能统一Web端和Native端请求资源的方式?
如果使用了动态下发配置文件来配置App的跳转逻辑,那么如果做到iOS和Android两边只要共用一套配置文件?
如果App出现bug了,如何不用JSPatch,就能做到简单的热修复功能?
比如App上线突然遇到了紧急bug,能否把页面动态降级成H5,ReactNative,Weex?或者是直接换成一个本地的错误界面?
如何在每个组件间调用和页面跳转时都进行埋点统计?每个跳转的地方都手写代码埋点?利用Runtime AOP ?
如何在每个组件间调用的过程中,加入调用的逻辑检查,令牌机制,配合灰度进行风控逻辑?
如何在App任何界面都可以调用同一个界面或者同一个组件?只能在AppDelegate里面注册单例来实现?
比如App出现问题了,用户可能在任何界面,如何随时随地的让用户强制登出?或者强制都跳转到同一个本地的error界面?或者跳转到相应的H5,ReactNative,Weex界面?如何让用户在任何界面,随时随地的弹出一个View ?
以上这些问题其实都可以通过在App端设计一个路由来解决。
因此,造一个轮子 KYRouter 路由,来解决这些问题。
已经有几款不错的 Router 了,如 JLRoutes, HHRouter, 但细看了下之后发现,还是不太满足需求。
JLRoutes 的问题主要在于查找 URL 的实现不够高效,通过遍历而不是匹配。还有就是功能偏多。
HHRouter 的 URL 查找是基于匹配,所以会更高效,KYRouter 也是采用的这种方法,但它跟 ViewController 绑定地过于紧密,一定程度上降低了灵活性。
KYRouter 呢?
模仿的JLRoutes的匹配不到会自动降级到global的思想。
URL 的处理一不小心,就容易散落在项目的各个角落,不容易管理。比如注册时的 pattern 是 ky://beauty/:id,然后 open 时就是 KY://beauty/123,这样到时候 url 有改动,处理起来就会很麻烦,不好统一管理。
所以 KYRouter
提供了一个类方法来处理这个问题。
#define TEMPLATE_URL @"qq://name/:name"
[KYRouter registerURLPattern:TEMPLATE_URL toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameters[name]:%@", routerParameters[@"name"]); // halfrost
}];
[KYRouter openURL:[KYRouter generateURLWithPattern:TEMPLATE_URL parameters:@[@"halfrost"]]];
}
generateURLWithPattern:
函数会对我们定义的宏里面的所有的:进行替换,替换成后面的字符串数组,依次赋值。
pod 'KYRouter', '~>1.0.0'
[KYRouter registerURLPattern:@"ky://foo/bar" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameterUserInfo:%@", routerParameters[KYRouterParameterUserInfo]);
}];
[KYRouter openURL:@"ky://foo/bar"];
当匹配到 URL 后,routerParameters
会自带几个 key
extern NSString *const KYRouterParameterURL;
extern NSString *const KYRouterParameterCompletion;
extern NSString *const KYRouterParameterUserInfo;
[KYRouter registerURLPattern:@"ky://category/travel" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameters[KYRouterParameterUserInfo]:%@", routerParameters[KYRouterParameterUserInfo]);
// @{@"user_id": @1900}
}];
[KYRouter openURL:@"ky://category/travel" withUserInfo:@{@"user_id": @1900} completion:nil];
[KYRouter registerURLPattern:@"ky://search/直播" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameters:%@", routerParameters);
}];
[KYRouter openURL:@"ky://search/直播"];
[KYRouter registerURLPattern:@"ky://" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"没有人处理该 URL,就只能 fallback 到这里了");
}];
[KYRouter openURL:@"ky://search/travel/china?has_travelled=0"];
[KYRouter registerURLPattern:@"ky://detail" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"匹配到了 url, 一会会执行 Completion Block");
// 模拟 push 一个 VC
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
void (^completion)() = routerParameters[KYRouterParameterCompletion];
if (completion) {
completion();
}
});
}];
[KYRouter openURL:@"ky://detail" withUserInfo:nil completion:^{
[self appendLog:@"Open 结束,我是 Completion Block"];
}];
URL 的处理一不小心,就容易散落在项目的各个角落,不容易管理。比如注册时的 pattern 是 ky://beauty/:id
,然后 open 时就是 ky://beauty/123
,这样到时候 url 有改动,处理起来就会很麻烦,不好统一管理。
所以 KYRouter 提供了一个类方法来处理这个问题。
+ (NSString *)generateURLWithPattern:(NSString *)pattern parameters:(NSArray *)parameters;
使用方式
#define TEMPLATE_URL @"ky://search/:keyword"
[KYRouter registerURLPattern:TEMPLATE_URL toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameters[keyword]:%@", routerParameters[@"keyword"]); // Hangzhou
}];
[KYRouter openURL:[KYRouter generateURLWithPattern:TEMPLATE_URL parameters:@[@"Hangzhou"]]];
}
这样就可以在一个地方定义所有的 URL Pattern,使用时,用这个方法生成 URL 就行了。
更多信息,请参考
demo
KYRouter 被许可在 MIT 协议下使用。查阅 LICENSE 文件来获得更多信息。