最后更新: 2018-1-20

JLRoutes 是在 github 上 Star 比较多的一个, 在各大平台也有介绍, 一些知识可以参考到下面的连接查看. 本文仅仅作为我的思考以及对应的心得;

一、 JLRoutes如何管理URLScheme以及对应的Handler

当调用 [JLRoutes globalRoutes]; 时候, 回去调用 + (instancetype)routesForScheme:(NSString *)scheme;, 想起代码如下;

static NSMutableDictionary *routeControllersMap = nil;

+ (instancetype)globalRoutes
{
return [self routesForScheme:JLRoutesGlobalRoutesScheme];
} + (instancetype)routesForScheme:(NSString *)scheme
{
JLRoutes *routesController = nil; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
routeControllersMap = [[NSMutableDictionary alloc] init];
}); if (!routeControllersMap[scheme]) {
routesController = [[self alloc] init];
routesController.scheme = scheme;
routeControllersMap[scheme] = routesController;
} routesController = routeControllersMap[scheme]; return routesController;
}

有上面可以看出, 实例化一个 JLRoutes之后,会生成一个 routeControllersMap 全局静态字典,key为URL scheme, Value 为JLRoutes 对象, JLRoutes 对应的 Scheme 唯一,但是对应的 Routes 可以有多个.

总结: JLRoutes 使用键值对形式保存;

二、JLRoutes 如何注册 URL Scheme

  1. 普通的url Scheme,
[[JLRoutes routesForScheme:@"JLRoutesOne"] addRoute:@"/:ViewController/:userID/:pass" handler:nil]

最终会生成一个 JLRRouteDefinition 对象, 里面包含了 scheme = JLRoutesOnepattern= /:ViewController/:userID/:passpriority 以及 patternComponents = [:ViewController, :userID, :pass] 还有 对应的回调 handlerBlock;

其实我们可以看出, JLRRouteDefinition 对象 已经保存了所有 URL相关的信息。

然后将 JLRRouteDefinitionJLRoutes 根据优先级对象管理起来; [self.routes addObject:route];

  1. 包含可选参数的URL;
[[JLRoutes globalRoutes] addRoute:"/path/:thing/(/a)(/b)(/c)" handler:nil]
+ (NSArray <NSString *> *)expandOptionalRoutePatternsForPattern:(NSString *)routePattern
{
/* this method exists to take a route pattern that is known to contain optional params, such as: /path/:thing/(/a)(/b)(/c) and create the following paths: /path/:thing/a/b/c
/path/:thing/a/b
/path/:thing/a/c
/path/:thing/b/a
/path/:thing/a
/path/:thing/b
/path/:thing/c
*/ if ([routePattern rangeOfString:@"("].location == NSNotFound) {
return @[];
} NSString *baseRoute = nil; // 分析点1:
NSArray *components = [self _optionalComponentsForPattern:routePattern baseRoute:&baseRoute];
// 分析点2
NSArray *routes = [self _routesForOptionalComponents:components baseRoute:baseRoute]; return routes;
}

分析点1:

通过 NSSCanner来解析开数据, 拆解可选部分与必选部分, baseRoute 为必选部分,components 为可选部分;

baseRoute = /path/:thing/
components = ["/a", "/b", "/c"]

分析点2:

此处就是将 components 拼接成一个个的url;

<__NSFrozenArrayM 0x60400024b370>(
/path/:thing//a/b/c,
/path/:thing//b/c,
/path/:thing//a/c,
/path/:thing//c,
/path/:thing//a/b,
/path/:thing//b,
/path/:thing//a,
/path/:thing/
)

深入进去还是比较有意思的,我们进去看看:

运用递归的想法.

逐步解析一下:

/c [/a, /b]

/b [/a]

/a []

递归回去

[[/a], []]

[[/a], [], [/a, /b], [/b]]

[[/a], [], [/a, /b], [/b], [/a, /c], [/c], [/a, /b, /c], [/b, /c]]

解析出来之后,将数组中的每一项,生成一个 JLRRouteDefinition 对象, 然后由 JLRoutes.routes来管理;

- (NSArray<NSArray *> *)JLRoutes_allOrderedCombinations
{
NSInteger length = self.count;
if (length == 0) {
return [NSArray arrayWithObject:[NSArray array]];
} id lastObject = [self lastObject];
NSArray *subarray = [self subarrayWithRange:NSMakeRange(0, length - 1)];
NSArray *subarrayCombinations = [subarray JLRoutes_allOrderedCombinations];
NSMutableArray *combinations = [NSMutableArray arrayWithArray:subarrayCombinations]; for (NSArray *subarrayCombos in subarrayCombinations) {
[combinations addObject:[subarrayCombos arrayByAddingObject:lastObject]];
} return [NSArray arrayWithArray:combinations];
}

三、 JLRoutes 调用

系统调用 OpenUrl,因为注册的Scheme为当前app 使用,因此会调用到 AppDelegate

-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
return [JLRoutes routeURL:url];
}

查看源代码,可以追溯到 -_routeURL:withParameters:executeRouteBlock:.

  1. 会根据url生成对应的 JLRRouteRequest; 将url进行一些列的拆分; host & Path & query

  2. 遍历 JLRoutes.routes里面的 JLRRouteDefinition, 判断能否根据 JLRRouteRequest来匹配,生成对应的 JLRRouteResponse,

    匹配规则比较简单,根据前面的 : *来设置;

  3. JLRoutes 还支持通配符;


四: 总结:

JLRoutes 相对来设比较简单的一个框架,但是实用性非常的高, 作者用一个全局的Map来保存对应的Scheme信息,解析 Url 成一个 request, 根据是否匹配生成对应的response, 然后进行设置。

设置很巧妙,

但是这个好像存在几个问题:

  1. 全局保存,如果成指数型的增长,可能占用较大内存;
  2. 对所有的handler 都需要提前注册进去

此框架使用了 NSSCanner 以及 NSURLCompenent

相关链接:

1. 官方的JLRoutes链接;

2. 我阅读的版本,已经fork过来

3. 可参考demo

源码阅读-JLRoutes路由设置的更多相关文章

  1. Yii2.0源码阅读-从路由到控制器

    之前的文章弄清了一次请求的开始到结束.主要讲了Yii Applicaton实例的创建.初始化,UrlManager如何返回Yii中的路由信息,到runAction,最后将Response发送给客户端. ...

  2. laravel5.5源码阅读草稿——路由

    laravel 里的路由是由RouteServiceProvider提供的,其中的boot方法为启动项,调用了父类的boot方法. RouteServiceProvider中的boot方法设置了自己与 ...

  3. Kibana源码分析--Hapijs路由设置理解笔记

    [ES6解构赋值]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_ ...

  4. Hadoop 副本放置策略的源码阅读和设置

    本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/hadoop_block_placement_policy 大多数 ...

  5. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

  6. 40 网络相关函数(八)——live555源码阅读(四)网络

    40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...

  7. 36 网络相关函数(四)——live555源码阅读(四)网络

    36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...

  8. 33 网络相关函数(一)——live555源码阅读(四)网络

    33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...

  9. gogs 源码阅读笔记 001

    gogs 源码阅读笔记 001 gogs项目相当不错,本笔记实际是基于gogs fork版本 git-122a66f. gitea (gitea版本由来)[https://blog.gitea.io/ ...

随机推荐

  1. MySQL -2- 体系结构-多实例模块

    0.在已创建mysql,port=3306的数据库前提下 需要删除/etc/.my.cnf再做以下操作 cp /etc/my.cnf /etc/my.cnf.3306 1.mkdir -p /u02/ ...

  2. SpringMVC上传文件总结

    如果是maven项目 需要在pom.xml文件里面引入下面两个jar包 <dependency> <groupId>commons-fileupload</groupId ...

  3. C++中的类型识别

    1,为什么会提出类型识别概念呢? 1,为什么在 C 语言中没有提出这个概念呢,就是因为在 C++ 中引入了面向对象的特性,面向对象里面有一个非常重要的原则就是赋值兼容性原则: 2,在面向对象中可能出现 ...

  4. hibernate update-->参数绑定

    Hibernate 更新数据库 参数绑定总结: 一.query.setParameter(属性名,真实值,类型); String hql="update User u set u.userN ...

  5. linux 内核数据结构之红黑树.

    转载: http://www.cnblogs.com/haippy/archive/2012/09/02/2668099.html https://zh.wikipedia.org/zh/%E7%BA ...

  6. 安装运行zookeeper的坑

    从官网下载zookeeper的地址中有俩文件 一个是apache-zookeeper-3.5.5.tar.gz ,另一个是apache-zookeeper-3.5.5-bin.tar.gz 若是使用前 ...

  7. sql server 三角函数

    正弦函数SIN(x)和反正弦函数ASIN(x) --SIN(x)返回x的正弦,其中x为弧度值 --ASIN(x)返回x的反正弦,即正弦x的值,若x不在-1到1的范围内,则返回NULL 示例:selec ...

  8. 大数据计算引擎之Flink Flink状态管理和容错

    这里将介绍Flink对有状态计算的支持,其中包括状态计算和无状态计算的区别,以及在Flink中支持的不同状态类型,分别有 Keyed State 和 Operator State .另外针对状态数据的 ...

  9. vue中使用stylus编写css

    安装步骤 cnpm install stylus --save-dev cnpm install stylus-loader --save-dev 写法如下: <style lang=" ...

  10. ES的索引、type、document、filer、mapping、id

    一.ES的存储结构 1.索引 es 中存储数据的基本单位,比如说你现在要在 es 中存储一些订单数据,你就应该在 es 中创建一个索引 order_idx,所有的订单数据就都写到这个索引里面去.看了一 ...