iOS路由简说

作者: 欢博 | 来源:发表于2018-04-14 20:01 被阅读928次

一、概念

        路由就是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,会自动匹配规则

相关文章

  • iOS路由简说

    一、概念 路由就是URL到函数的映射;对于客户端来说,就是把URL映射到响应的类或者controller。 如何能...

  • iOS 路由总结大全

    iOS路由介绍 iOS路由目前业内流行的有两大分类:1、基于URL或protocol的注册调度型路由 2、runt...

  • iOS 解藕、组件化最佳实践

    iOS 解藕、组件化最常用的是使用统跳路由的方式,目前比较常用的 iOS 开源路由框架主要是JLRoutes、MG...

  • 『Flutter』路由正向逆向传值

    flutter路由跳转,在看过ios的路由,vue的路由,其实对于路由已经有了一些了解。 这里需要学习的是flut...

  • IOS 页面切换

    写ios应用的页面切换不比写网页容易,网页应用可通过路由控制页面的跳转,而 ios 应用没有路由概念,所以页面跳转...

  • OpenUrl

    iOS-使用URL Schemes,进行应用之间跳转iOS - JLRoutes路由跳转官方文档JLRoutes ...

  • 理解Flutter中的路由管理

    路由的理解 移动端,前端中的路由指的是页面;例如: Android中activity, IOS中的ViewCont...

  • Flutter学习之:iOS原生与Flutter交互

    在iOS原生项目中指定路由打开Flutter页面 iOS代码 flutter代码 在iOS原生项目中与Flutte...

  • iOS组件化-路由设计思路

    https://xiaozhuanlan.com/topic/1537824960 iOS开发路由设计思路

  • ios 路由

    项目中使用路由方式 1.0 深度链接 2.0 推送 3.0 站内信 4.0 web跳转 1. 深度链接 简介 深度...

网友评论

    本文标题:iOS路由简说

    本文链接:https://www.haomeiwen.com/subject/hoxrkftx.html