最后更新: 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. Magic Potion(网络流)

    原题链接 2018南京的铜牌题,听说学长他们上来就A了,我这个图论选手也就上手做了做,结果一言难尽...... 发此篇博客希望自己能牢记自己的菜... 本题大意:有n个heros和m个monsters ...

  2. Integer类的常量池

  3. 【6.12校内test】T3 城市交通费

    要不我先去写T2吧(逃 先把题目搞上来: [问题描述] 有 n 个城市,编号 1~n.其中 i 号城市的繁华度为 pi.省内有 m 条可以双向同行的高速 公路,编号 1~m.编号为 j 的高速公路连接 ...

  4. vim编辑Dockerfile时语法高亮

    参考Dockerfile构建容器---语法高亮 三个文件扔进相关的目录即可 1. /usr/share/vim/vimfiles/doc/dockerfile.txt *dockerfile.txt* ...

  5. wex5 如何写后台BAAS

    Data.java: 在class中链接数据源: 配置的numsql数据源 private static final String DATASOURCE_NUMYSQL = "numysql ...

  6. docker之本地连接

    docker安装成功,之后我们需要连接进入docker中,这里罗列连接方式 1. Windows7 一般的虚拟ip地址: 192.168.99.100 查看ip地址: 1)  C:\Users\thi ...

  7. 帝国cms 项目搬家换域名修改详情页图片路径

    update phome_ecms_news_data_1 set newstext=REPLACE (newstext,'/d/file/','http://www.xxxx.com/d/file/ ...

  8. roll out项目中原系统自定义程序不能编辑

    1.SE38编辑时报 程序源系统与现阶段系统不一致:Carry out repairs in non-original systems only if urgent 2.SE16N 查看表TADIR, ...

  9. unittest assert断言

    unittest常用的断言方法 1.assertEqual(self, first, second, msg=None) --判断两个参数相等:first == second 2.assertNotE ...

  10. KVM安装配置笔记

    系统环境centos6.6 一.KVM安装前系统相关操作: (1)修改内核模式为兼容内核启动 # grep -v "#" /etc/grub.confdevice (hd0) HD ...