读JLRoutes源码

上个项目虽然使用的是Swift,因为当时时间比较紧,没看到合适的路由库,就用了JLRoutes,现在的项目路由感觉设计方面有很多问题,先读读JLRoutes的源码吧

简介

JLRoutes是一个简单的基于block的URL路由库。它设计为在应用中只要使用少量的代码就可以轻松处理复杂URL Schemes。

简单的使用方式

注册路由及其回调

JLRoutes *routes = [JLRoutes globalRoutes];
[routes addRoute:@"/user/view/:userID" handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
    
    NSString *userID = parameters[@"userID"];
    
    return YES;
}];

调用

NSURL *viewUserURL = [NSURL URLWithString:@"myapp://user/view/joeldev"];
[JLRoutes routeURL:viewUserURL];

移除

[[JLRoutes globalRoutes] removeRouteWithPattern:@"/user/view/:userID"];

各个类分工

JLRRouteRequest 模型类,表示路由URL的一个请求;解析为子路径和请求参数,然后由JLRouteDefinition使用这些参数进行匹配;

JLRRouteResponse 是尝试路由一个JLRRouteRequest时的响应;

JLRRouteHandler 是一个帮助类,用于创建要传给addRoute:调用的处理block;

JLRParsingUtilities 路由解析工具类;

JLRRouteDefinition 是一个模型对象,表示已注册的路由,包括URL scheme、路由pattern、优先级等; 可以子类重写-routeResponseForRequest:方法来自定义路由解析行为;可以重写-callHandlerBlockWithParameters来自定义传给handlerBlock的参数;

基本原理

看到注册然后调用这样的操作,应该猜测到相关的套路为一定存在一个常驻内存的集合保存着刚注册的信息,url为key,block为value;当打开一个url时,即遍历集合然后执行相应的block;

观察一下库提供的接口和使用方式,是否有一种似曾相识的感觉呢,B/S模式,用户在浏览器上输入URL,服务器给出响应,跳转到相关的页面,是不是和现在看到的库的行为类似,不过类比的有点牵强;当然,本来路由的概念和思想就是从前端借鉴过来的;

一套操作下来,自定义路由解析等还是功能花样挺多的;

静态变量JLRGlobal_routeControllersMap保存所有的信息;

学到的新知识

JLRParsingUtilities.m

  1. 有 NSArray (JLRoutes_Utilities) 、NSString (JLRoutes_Utilities)分类,把几个类写在同一个文件中还算是常规写法,这里写在.m中起到了私有封装的效果,逻辑上也很清晰;
  2. 虽然常用高阶函数,没了解过是怎么实现的,这里有实现了高阶函数map和filter;
  3. 如何用递归求可选参数所有组合,
  4. 数组的排序方法sortedArrayUsingDescriptors:,NSSortDescriptor(如何根据集合中对象共有的属性来排序的不可变描述对象)))
  5. NSScanner的使用(同样用的少的类还有谓词NSPredicate、正则NSRegularExpression);
  6. hash方法在什么时候会调用?一个对象作为key值时,会调用hash方法,用以生成一个唯一标识符;(NSDictionary需要唯一key查找对象,NSSet需要根据hash值过滤重复对象;)对于基本类型,==运算符比较的是值;对于对象类型,==运算法比较的是对象的地址;(hash方法,不关心地址是否相同,只对内容进行区分时,一般是对关键属性的hash值进行异或运算;如果期望对于地址不同、但是内容相同的对象做区分,则用[super hash]);

引用源

Written on September 9, 2019