关于URL Schemes的使用和设置
在info文件创建对应的Schemes,app会根据这个Schemes做为app间的跳转标识。
1、JLRoutes先注册Schems
JLRoutes(forScheme:"JLRoutesThree")
2、注册路由规则
addRoute("/:object/:primaryKey")
3、openURl时获取的数据按字典返回
(parameters) -> Bool in
let object = parameters["object"];
let primaryKey = parameters["primaryKey"];
return true
}
完整创建
JLRoutes(forScheme:"JLRoutesThree").addRoute("/:object/:primaryKey") { (parameters) -> Bool in
let object = parameters["object"];
let primaryKey = parameters["primaryKey"];
return true
}
JLRoutes调用URL
LRoutes.routeURL(url)
JLRoutes的实现原理
JLRoutes的初始化
+ (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
,用Schems
作为key来保存JLRoutes
对象,根据这个Schemes
来返JLRoutes
对象。
addRoute:
- (void)addRoute:(NSString *)routePattern priority:(NSUInteger)priority handler:(BOOL (^)(NSDictionary *parameters))handlerBlock
{
//该方法用来判断规则上是否有(),把括号去掉
NSArray *optionalRoutePatterns = [JLROptionalRouteParser expandOptionalRoutePatternsForPattern:routePattern];
if (optionalRoutePatterns.count > 0) {
// there are optional params, parse and add them
for (NSString *route in optionalRoutePatterns) {
[self _verboseLog:@"Automatically created optional route: %@", route];
[self _registerRoute:route priority:priority handler:handlerBlock];
}
return;
}
[self _registerRoute:routePattern priority:priority handler:handlerBlock];
}
先做routePattern
route规则是否存在有()的情况和去()操作。
然后注册该规则_registerRoute:
registerRoute:
- (void)_registerRoute:(NSString *)routePattern priority:(NSUInteger)priority handler:(BOOL (^)(NSDictionary *parameters))handlerBlock
{
JLRRouteDefinition *route = [[JLRRouteDefinition alloc] initWithScheme:self.scheme pattern:routePattern priority:priority handlerBlock:handlerBlock];
if (priority == 0 || self.routes.count == 0) {
[self.routes 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.routes copy]) {
if (existingRoute.priority < priority) {
// if found, add the route after it
[self.routes 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.routes addObject:route];
}
}
}
创建JLRRouteDefinition
对象来保存,该规则的优先级(priority),和回调操作(handlerBlock)等信息
遍历self.routes
数组,根据priority
的大小来加入数组中。
调用LRoutes.routeURL(url)
- (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];
for (JLRRouteDefinition *route in [self.routes copy]) {
// check each route for a matching response
JLRRouteResponse *response = [route routeResponseForRequest:request decodePlusSymbols:shouldDecodePlusSymbols];
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];
[self _verboseLog:@"Final parameters are %@", finalParameters];
didRoute = [route callHandlerBlockWithParameters: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;
}
遍历self.routes
,找到可以匹配该url的JLRRouteDefinition
,然后把url解析成字典,然后就调用block把字典传出[route callHandlerBlockWithParameters:finalParameters];
。