阅读源码是目前沉淀自己的最好方式~

route 都是知道什么意思,路由的意思,如果没接触vue之前我对路由也只是了解的比较浅,但现在还算可以了。当然 JLRoutes路由跟vue还是有差别的。它是用了类似window.location.href="http://www.xxx.com/path?params=xxx"这种方式。这算是点开胃菜吧。
如果要搞懂JLRoutes必须要搞懂的就是url的链接组成了。
http://www.xxxx.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
- http: 是协议部分 后面//为分隔符 这里可以使http也可以是https各种协议
- www.xxxx.com 域名 当然也可以用ip作为域名地址 比如这里换成192.168.1.124也是可以的
- 8080 端口号 域名和端口号用www.xxxx.com分开
4./news/ 虚目录部分
5.index.asp文件名
6.最后面的#name是锚
7.?boardID=5&ID=24618&page=1 这里是参数部分
JLRoutes组成
JLRoutes //这是我们主要接触到的类 里面包含了各种注册方法 取消注册方法
The JLRoutes class is the main entry-point into the JLRoutes framework. Used for accessing schemes, managing routes, and routing URLs.
JLRParsingUtilities //解析路由的工具类
JLRRouteDefinition//根据路由拼接成我们需要的params
JLRRouteDefinition is a model object representing a registered route, including the URL scheme, route pattern, and priority.
JLRRouteRequest //这个也是拼接我们需要的params
JLRRouteRequest is a model representing a request to route a URL.
It gets parsed into path components and query parameters, which are then used by JLRRouteDefinition to attempt a match.
JLRRouteResponse // JLRRouteResponse is the response from attempting to route a JLRRouteRequest.
根据一条条线分析源码
先看一个方法
[[JLRoutes routesForScheme:scheme] addRoute:@"/push/:controller"handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
Class class = NSClassFromString(parameters[@"controller"]);
UIViewController *nextVC = [[class alloc] init];
[self paramToVc:nextVC param:parameters];
UIViewController *currentVc = [self currentViewController];
[currentVc.navigationController pushViewController:nextVC animated:YES];
return YES;
}];
先看init这条线
+ (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;
}
我们可以看到routeControllersMap这个字典,被放到单例里面进行初始化,所以JLRoutes中的路由其实就是在这里面啦。
registerRoute 注册
- (void)addRoutes:(NSArray<NSString *> *)routePatterns handler:(BOOL (^)(NSDictionary<NSString *, id> *parameters))handlerBlock //这个handlerBlock就是回调函数哦
{
for (NSString *routePattern in routePatterns) {
[self addRoute:routePattern handler:handlerBlock];
}
}
一直往下走
- (void)addRoute:(NSString *)routePattern priority:(NSUInteger)priority handler:(BOOL (^)(NSDictionary<NSString *, id> *parameters))handlerBlock
{
NSArray <NSString *> *optionalRoutePatterns = [JLRParsingUtilities expandOptionalRoutePatternsForPattern:routePattern];
JLRRouteDefinition *route = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:routePattern priority:priority handlerBlock:handlerBlock];//在这个地方
if (optionalRoutePatterns.count > 0) {
// there are optional params, parse and add them
for (NSString *pattern in optionalRoutePatterns) {
[self _verboseLog:@"Automatically created optional route: %@", route];
JLRRouteDefinition *optionalRoute = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:pattern priority:priority handlerBlock:handlerBlock];
[self _registerRoute:optionalRoute];
}
return;
}
[self _registerRoute:route];
}
先看 [self _registerRoute:optionalRoute]; 这个函数
- (void)_registerRoute:(JLRRouteDefinition *)route
{
if (route.priority == 0 || self.mutableRoutes.count == 0) {
[self.mutableRoutes addObject:route];
} else {
NSUInteger index = 0;
BOOL addedRoute = NO;
// search through existing routes looking for a lower priority route than this one
for (JLRRouteDefinition *existingRoute in [self.mutableRoutes copy]) {
if (existingRoute.priority < route.priority) {
// if found, add the route after it
[self.mutableRoutes insertObject:route atIndex:index];
addedRoute = YES;
break;
}
index++;
}
// if we weren't able to find a lower priority route, this is the new lowest priority route (or same priority as self.routes.lastObject) and should just be added
if (!addedRoute) {
[self.mutableRoutes addObject:route];
}
}
}
我们可以看到route加到了一个由单例保存的,可变数组中。其实这一步就完成了注册路由的过程。
回调函数 handlerBlock
JLRRouteDefinition *route = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:routePattern priority:priority handlerBlock:handlerBlock];//在这个地方 会拼接路由
- (instancetype)initWithScheme:(NSString *)scheme pattern:(NSString *)pattern priority:(NSUInteger)priority handlerBlock:(BOOL (^)(NSDictionary *parameters))handlerBlock
{
if ((self = [super init])) {
self.scheme = scheme;
self.pattern = pattern;
self.priority = priority;
self.handlerBlock = handlerBlock; //在这里会把这个block保存到 JLRRouteDefinition对象中,记住,会保存在这
if ([pattern characterAtIndex:0] == '/') {
pattern = [pattern substringFromIndex:1];
}
self.patternComponents = [pattern componentsSeparatedByString:@"/"];
}
return self;
}
点击页面跳转 配合 handlerBlock 回调
NSString *url = @"RouteScheme://push/XHTestController?titleText=fromFirst&love=哈哈";
NSCharacterSet *allowCharacters = [[NSCharacterSet characterSetWithCharactersInString:name] invertedSet];
NSString *encodedUrl = [url stringByAddingPercentEncodingWithAllowedCharacters:allowCharacters];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:encodedUrl]];
当调用openURL的时候,会调用系统
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
return [[JLRoutes routesForScheme:@"Route"]routeURL:url];
这里的url就是上面的RouteScheme://push/XHTestController?titleText=fromFirst&love=哈哈
}
继续往下走
- (BOOL)routeURL:(NSURL *)URL
{
return [self _routeURL:URL withParameters:nil executeRouteBlock:YES];
}
下面这个方法有点长,不过我都会在代码里标上解析
- (BOOL)_routeURL:(NSURL *)URL withParameters:(NSDictionary *)parameters executeRouteBlock:(BOOL)executeRouteBlock
{
if (!URL) {
return NO;
}
[self _verboseLog:@"Trying to route URL %@", URL];
BOOL didRoute = NO;
JLRRouteRequest *request = [[JLRRouteRequest alloc] initWithURL:URL alwaysTreatsHostAsPathComponent:alwaysTreatsHostAsPathComponent];//在这里初始化一个request对象在对象里拼接后面我们需要的 pathComponents queryParams URL
for (JLRRouteDefinition *route in [self.mutableRoutes copy]) {//遍历刚刚保存路由的可变数组 在这里为了防止发生变化,把他改了不可变数组
// check each route for a matching response
JLRRouteResponse *response = [route routeResponseForRequest:request decodePlusSymbols:shouldDecodePlusSymbols]; //因为这里我们需要遍历数组中保存的每一个路由,所以我们会根据respones里面的ismatch来进行判断,选出我们当前在用的那个路由,其他的路由直接跳出循环
if (!response.isMatch) {
continue;
}
[self _verboseLog:@"Successfully matched %@", route];
if (!executeRouteBlock) {
// if we shouldn't execute but it was a match, we're done now
return YES;
}
// configure the final parameters
NSMutableDictionary *finalParameters = [NSMutableDictionary dictionary];
[finalParameters addEntriesFromDictionary:response.parameters];
[finalParameters addEntriesFromDictionary:parameters]; //在这里拼接处最后需要返回handlerBlock中的参数 请看下图
[self _verboseLog:@"Final parameters are %@", finalParameters];

didRoute = [route callHandlerBlockWithParameters:finalParameters];//请注意看里,这里直接调用callHandlerBlockWithParameters这个函数走block,把finalParameters传到外面。
到这里大体的一个流程我们就走了一遍。
if (didRoute) {
// if it was routed successfully, we're done
break;
}
}
if (!didRoute) {
[self _verboseLog:@"Could not find a matching route"];
}
// if we couldn't find a match and this routes controller specifies to fallback and its also not the global routes controller, then...
if (!didRoute && self.shouldFallbackToGlobalRoutes && ![self _isGlobalRoutesController]) {
[self _verboseLog:@"Falling back to global routes..."];
didRoute = [[JLRoutes globalRoutes] _routeURL:URL withParameters:parameters executeRouteBlock:executeRouteBlock];
}
// if, after everything, we did not route anything and we have an unmatched URL handler, then call it
if (!didRoute && executeRouteBlock && self.unmatchedURLHandler) {
[self _verboseLog:@"Falling back to the unmatched URL handler"];
self.unmatchedURLHandler(self, URL, parameters);
}
return didRoute;
}
通过
[[JLRoutes routesForScheme:scheme] addRoute:@"/push/:controller"handler:^BOOL(NSDictionary<NSString *,id> * _Nonnull parameters) {
}];
我们可以很清楚的看到,通过一系列的骚操作,把跳转页面的操作搞到了一起。
后面还会另开新篇找些JLRoutes的复杂运用。
网友评论