源码阅读-JLRoutes路由设置
最后更新: 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
- 普通的url Scheme,
[[JLRoutes routesForScheme:@"JLRoutesOne"] addRoute:@"/:ViewController/:userID/:pass" handler:nil]
最终会生成一个 JLRRouteDefinition
对象, 里面包含了 scheme = JLRoutesOne
、pattern= /:ViewController/:userID/:pass
、priority
以及 patternComponents = [:ViewController, :userID, :pass]
还有 对应的回调 handlerBlock
;
其实我们可以看出, JLRRouteDefinition
对象 已经保存了所有 URL相关的信息。
然后将 JLRRouteDefinition
让 JLRoutes
根据优先级对象管理起来; [self.routes addObject:route];
- 包含可选参数的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:
.
会根据url生成对应的
JLRRouteRequest
; 将url进行一些列的拆分;host
&Path
&query
遍历
JLRoutes.routes
里面的JLRRouteDefinition
, 判断能否根据JLRRouteRequest
来匹配,生成对应的JLRRouteResponse
,
匹配规则比较简单,根据前面的 : *来设置;JLRoutes 还支持通配符;
四: 总结:
JLRoutes 相对来设比较简单的一个框架,但是实用性非常的高, 作者用一个全局的Map来保存对应的Scheme信息,解析 Url 成一个 request, 根据是否匹配生成对应的response, 然后进行设置。
设置很巧妙,
但是这个好像存在几个问题:
- 全局保存,如果成指数型的增长,可能占用较大内存;
- 对所有的handler 都需要提前注册进去
此框架使用了 NSSCanner
以及 NSURLCompenent
相关链接:
1. 官方的JLRoutes链接;
2. 我阅读的版本,已经fork过来
3. 可参考demo
源码阅读-JLRoutes路由设置的更多相关文章
- Yii2.0源码阅读-从路由到控制器
之前的文章弄清了一次请求的开始到结束.主要讲了Yii Applicaton实例的创建.初始化,UrlManager如何返回Yii中的路由信息,到runAction,最后将Response发送给客户端. ...
- laravel5.5源码阅读草稿——路由
laravel 里的路由是由RouteServiceProvider提供的,其中的boot方法为启动项,调用了父类的boot方法. RouteServiceProvider中的boot方法设置了自己与 ...
- Kibana源码分析--Hapijs路由设置理解笔记
[ES6解构赋值]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_ ...
- Hadoop 副本放置策略的源码阅读和设置
本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/hadoop_block_placement_policy 大多数 ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- 36 网络相关函数(四)——live555源码阅读(四)网络
36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...
- 33 网络相关函数(一)——live555源码阅读(四)网络
33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...
- gogs 源码阅读笔记 001
gogs 源码阅读笔记 001 gogs项目相当不错,本笔记实际是基于gogs fork版本 git-122a66f. gitea (gitea版本由来)[https://blog.gitea.io/ ...
随机推荐
- gRPC编译教程
windows平台的编译 一.编译openssl ① 安装perl(可以使用ActivePerl),执行perl Configure VC-WIN64A no-asm .在这里解释一下参数含义,VC- ...
- JavaScript数组知识
JavaScript数组知识 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- a页面通过url传值,b页面如何接收(jquery.params.js实现)
用于两个html页面之间的传值 我的应用场景是:用echarts在a页面做完中国地图后,点击某个省份在b页面显示某个省份的地图.(在b页面显示点击了的那个省份的地图,等于说b页面是个“容器”页) 假设 ...
- 关于encodeURI() 踩的坑
情景: 列表页跳转详情页,需要把列表页的数据带到详情页直接展示,思路是在路径后面加?传参,然后再在详情页获取url的参数. 为了以防中文乱码什么的所以先试用encodeURI转码再decodeURI解 ...
- 096、运行第一个Service (Swarm03)
参考https://www.cnblogs.com/CloudMan6/p/7874609.html 上一节我们部署好了 Swarm 集群,下面部署一个运行httpd镜像的service进行演示 ...
- Python 描述符 (descriptor)
1.什么是描述符? 描述符是Python新式类的关键点之一,它为对象属性提供强大的API,你可以认为描述符是表示对象属性的一个代理.当需要属性时,可根据你遇到的情况,通过描述符进行访问他(摘自Pyth ...
- vue中出现 There are multiple modules with names that only differ in casing的问题
import时,文件引入的路径描述不统一,所以保留一种引入风格即可解决. 第一种,我选择统一用第一种 import GoTop from '@/components/layout/goTop' 第二种 ...
- 剑指offer-2:斐波那契数列
二.斐波那契数列 题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 1.递归法 1). 分析 斐波那契数列的标准公式为 ...
- webpack3 打包
1. 基于 webpack 3.0 2.步骤.说明 2.1 webpack 本地初始化.安装基本包 npm init > package.json npm i webpack ...
- iOS-NSLog发布时取消打印日志
1 选择工程的Target -> Build Settings -> Preprocessor Macros. 如图,默认 Debug项,是“DEBUG=1”. 2 在程序中设置全局宏定义 ...