iOS路由简说

一、概念

        路由就是URL到函数的映射;对于客户端来说,就是把URL映射到响应的类或者controller。

        如何能把URL映射到我们已经开发的类或者controller中呢,这就需要我们首先要为其添加一个配置表,该配置表定义了URL的规则和映射的目标。

二、路由能解决哪些问题

1、 降低App页面之间的耦合性。随着项目越来越负责,各个组件和页面之间的跳转也变得越来越复杂,他们之间的跳转逻辑也变的越来越紧密,这就造成了各个模块的相互依赖越来越紧密

2、 统一各个端(iOS、Android、Web)之间实现跳转页面的统一性

3、 可以通过动态下发配置表来配置App的跳转逻辑。这样iOS和Android两边只要共用一套配置文件,通过下发修改后配置表也能实现动态的改变映射目标。

三、资源的定义

在Android与iOS系统中,均支持URL Scheme,通过app内协定的Scheme,进行唤醒app和参数的传递。例如QQ(mqq://)、支付宝(alipay://)等。

四、实现的流程

1、路由的流程实现,如下图所示,我们确定路由需要做哪些事 

1.1 A模块调用路由,为表达自己需要调用的是B模块,考虑到H5、推送以及其他App 的外部调用,可以使用URL这种方式来定义目标,也就是说用URL来表示目标B

1.2对一个URL的请求来说,路由需要有统一的回调处理,当然,如果不需要回调也是可以的,回调是需要目标去触发的

1.3路由要有处理URL的功能,并调用其他模块的能力

2、路由的逻辑结构


五、路由的使用

        以下是我从Github上面找的一些路由方案,按照Star从高到低排列。依次来分析一下它们各自的设计思路。

1、WLRRoute

1.1类图结构


1.2 类说明:

(1)WLRRouteRequest,路由层的请求,无论是跨应用的外部调用还是内部调用,最后都形成一个路由请求,该请求包含了URL上的queryparameters和路径参数,还有内部调用时直接传入的原生参数,还有请求发起者对目标预留的回调block。

(2)WLRRouteHandler,路由层的handler处理,handler接收一个WLRRouteRequest对象,来完成是否是界面跳转,还是组件加载,还是内部逻辑。

(3)WLRRouter,路由核心对象,内部持有注册的Handler和匹配Matcher;负责界面跳转的Handler,负责组件加载的Handler,负责API的Handler;负责URL匹配的Matcher,则是则是处理请求函数和路径信息。路由的作用就是将外部调用传入的URL或者是内部调用传入的target,在内部匹配上对应的handler,然后调用生命周期方法,完成处理过程,当然,图中还有route的中间件,实际上是预留AOP的口子,方面后期扩展。

(4)WLRRouteMatcher,用以处理外部调用的URL是否能与预设的正则表达式匹配,每一个匹配规则对应一个WLRRouteMatcher, 在WLRRouter中,每一次注册一个规则都会生成一个WLRRouteHandler和WLRRouteMatcher与之对应。

(5)WLRRegularExpression,继承NSRegularExpression,用以匹配URL,WLRRouteMatcher内部有一个WLRRegularExpression对象,WLRRouteMatcher接受一个URL,会使用WLRRegularExpression生成一个WLRMatchResult对象,来确定是否匹配成功,如果匹配成果则将URL上的路径参数给取出来。

(6)WLRMatchResult,用以描述WLRRegularExpression的匹配结果,包含路径参数和请求参数。

1.3工作流程

(1)App启动实例化WLRRouter对象

(2)实例化WLRRouteHandler对象和匹配规则表达式

(3)WLRRouter对象挂载URL的表达式相对应WLRRouteHandler实例,同时根据匹配规则生成一个WLRRouteMatcher对象,用以处理符合此规则的URL。

(4)外部调用的URL和callback传入WLRRouter对象

(5)WLRRouter对象遍历内部持有的URL的匹配表达式,并找到每一个WLRRouteMatcher对象,将URL传入看是否能返回WLRRouteRequest对象

(6)将WLRRouteRequest对象传入对应的WLRRouteHandler对象。

(7)WLRRouteHandler对象根据WLRRouteRequest寻找到TargetViewController和SourceViewController,在生命周期函数里,完成参数传递与视图转场。

1.4调用实现

(1)实现WLRUserHandler继承WLRRouteHandler,用于实现目标对象处理跳转,主要对以下方法进行重写:

//handle处理一个请求

- (BOOL)shouldHandleWithRequest:(WLRRouteRequest *)request;

//根据request取出调用的目标视图控制器

-(UIViewController *)targetViewControllerWithRequest:(WLRRouteRequest *)request;

//根据request取出来源的视图控制器

-(UIViewController *)sourceViewControllerForTransitionWithRequest:(WLRRouteRequest *)request;

//开始进行转场

-(BOOL)transitionWithRequest:(WLRRouteRequest *)request error:(NSError *__autoreleasing *)error;

       (2)注册路由规则和处理handle

self.router = [[WLRRouter alloc]init]; 

[self.router registerHandler:[[WLRUserHandler alloc]init] forRoute:@“/user/:phone([0-9]+)"];


           也可以通过添加Block的为处理handle,如下

[self.router registerBlock:^WLRRouteRequest *(WLRRouteRequest *request) {  return request } forRoute:@“/user/:phone([0-9]+)”];

说明:该request中含有URL匹配解析出的路由参数和请求参数,分别为routeParameters和queryParameters;另primitiveParams为原生调用时的传值

     (3)当通过Scheme唤起app或者通过直接调用路由进行跳转时调用下面方法实现:

          [self.router handleURL:[NSURL URLWithString:@“scheme://myapp/user/13500000000"] primitiveParameters:@{@"user":@"nihao"}  targetCallBack:^(NSError *error, id responseObject) { NSLog(@"UserCallBack"); } withCompletionBlock:^(BOOL handled, NSError *error) { NSLog(@"UserHandleCompletion"); }];

其中primitiveParameters为app内调用跳转时指定数据,可为空;targetCallBack:为目标匹配的回调;withCompletionBlock:执行完跳转的回调。

2、JLRoutes

其本质可以理解为:保存一个全局的Map,key是url,value是对应存放block的数组,url和block都会常驻在内存中,当打开一个URL时,JLRoutes就可以遍历 , 这个全局的map,通过url来执行对应的block。

2.1 JLRoutes类说明

(1)routeControllersMap 是全局的单例可变字典。

(2)这个字典的 key 值对应一个标识,源码中称之为 scheme,为了不混淆,咱们就叫其为 JLRoutes 对象标识。这个标识对应的value 值为 routesController(JLRoutes类的对象:JLRoutes *routesController)。

(3)JLRoutes的对象(routesController)有很多属性,常用的有两个属性:NSString *scheme:也就是上面所说的 JLRoutes对象标识,也就是说,此 value 值记录了自己的 key 值。

(4)NSMutableArray *routes:此数组中存放了JLRRouteDefinition 对象。

(5)JLRRouteDefinition 对象为最终的具体模型,也就是说你注册的跳转逻辑的所有信息,都存在于这个模型中,包括要实施操作的handlerBlock(执行操作的block代码块)、scheme(JLRoutes对象标识)、pattern(模式)、priority(优先级)。

2.2工作流程

(1)App启动根据Scheme实例化JLRoutes对象和添加路由规则,一个规则对应一个JLRoutes对象,存储在全局routeControllersMap中。

(2)外部调用时,实例化JLRRouteRequest对象并解析出路径参数和请求参数存放在pathComponents和queryParams中。

(3)通过遍历routeControllersMap中的JLRoutes对象,找出能匹配URL规则的JLRoutes,同时返回匹配结果JLRRouteResponse。

(4)最后调用调用JLRoutes的处理结果的Block,由实现者实现目标的跳转。

2.3调用实现

(1)注册路由Scheme和添加路由规则

[[JLRoutes routesForScheme:@“RouteOne"]addRoute:@"/:phone" handler:^BOOL(NSDictionary * parameters) {

//处理匹配结果 进行跳转

                return YES;

    }];

(2)由JLRoutes调用routeURL传入URL,根据URL创建JLRRouteRequest并解析出路由路径和请求参数。

(3)匹配JLRoutes的匹配规则,取出路径上的有效参数

(4)调用跳转的处理Block,进行页面的目标跳转

3、WLRRoute 和 JLRoutes的差异化

3.1 JLRoutes 

(1)缺乏规则匹配的能力,不支持正则表达式匹配。

(2)代码逻辑简单,容易上手,不需要重写处理类。

(3)路由规则跳转逻辑为Block实现。

(4)各个业务模块间的耦合性高。

(5)调用时需指定使用的Scheme,

3.2 WLRRoute 

(1)具有强大的匹配能力,支持正则表达式的匹配。

(2)每个路由规则都对应一个Handle类,所以需重写其handle处理类,也可指定Block来定制跳转的目标页面。

(3)各个业务模块间的耦合性低

(4)调用时无需指定使用的Scheme,会自动匹配规则

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容