iOS使用核心的50行代码撸一个路由组件

iOS使用核心的50行代码撸一个路由组件,第1张

概述iOS使用核心的50行代码撸一个路由组件 使用组件化是为了解耦处理,多个模块之间通过协议进行交互.而负责解析协议,找到目的控制器,或者是返回对象给调用者的这个组件就是路由组件.本文讲解如何使用核心的50行代码实现一个路由组件. 组件化和路由 路由的实现 路由注册实现 路由使用实现 客户端的使用 一些小想法 组件化和路由 之前看过挺多的关于路由管理.路由处理的文章,常常会和组件化出现在一起,一开始不知道为何路由和组件化出现在一起,后来公司的项目中使用了路由组件(他本身也是一个组件,确切的说是一个中间人或者中介者),才突然想明白了,原来如此

使用组件化是为了解耦处理,多个模块之间通过协议进行交互。而负责解析协议,找到目的控制器,或者是返回对象给调用者的这个组件就是路由组件。本文讲解如何使用核心的50行代码实现一个路由组件。

组件化和路由路由的实现路由注册实现
路由使用实现客户端的使用一些小想法

组件化和路由

之前看过挺多的关于路由管理、路由处理的文章,常常会和组件化出现在一起,一开始不知道为何路由和组件化出现在一起,后来公司的项目中使用了路由组件(他本身也是一个组件,确切的说是一个中间人或者中介者),才突然想明白了,原来如此。

使用组件化是为了解耦处理,多个模块之间通过协议进行交互。而负责解析协议,找到目的控制器,或者是返回对象给调用者的这个组件就是路由组件。

路由组件的职责主要是:

给注册者提供注册接口

注册者传递path和path对应的block,block的具体实现又注册者自己处理

给调用者提供使用接口

调用者最简单可以传递一个path给路由组件发起调用,路由组件会把具体的处理转发给注册者,理论上是可以任意的 *** 作,包括页面跳转、d窗提示、返回一个值给调用者等

下面会会在以上分析的基础上实现一个简单的路由组件,对应的代码可以在YTRouterDemo这里找到

路由的实现

路由的实现包括两部分:路由注册实现以及路由使用实现

路由注册实现

路由注册实现时序图:


如上图所示,步骤很简单:

初始化一个YTRouteractionObject对象,用于保存path和对应的blok获取到路径对应的节点,path会使用"/"符拆分为多个pathItem,每个pathItem都会保存在一个Dictionary对应的位置上,subrouterMapWithPath负责深度遍历Dictionary,然后找到对应的位置把YTRouteractionObject对象保存在上一步找到的位置中

以上步骤对应的代码如下:

- (voID)registerPath:(Nsstring *)path actionBlock:(RouteractionBlock)actionBlock { YTRouteractionObject *actionObject = [YTRouteractionObject new]; actionObject.path = path; actionObject.actionBlock = actionBlock; NSMutableDictionary *subrouter = [self subrouterMapWithPath:path]; subrouter[YTRouteractionObjectKey] = actionObject;}- (NSMutableDictionary *)subrouterMapWithPath:(Nsstring *)path { NSArray *components = [path componentsSeparatedByString:@"/"]; NSMutableDictionary *subrouter = self.routerMap; for (Nsstring *component in components) {  if (component.length == 0) {   continue;  }  if (!subrouter[component]) {   subrouter[component] = [NSMutableDictionary new];  }  subrouter = subrouter[component]; } return subrouter;}

在Demo中注册的几个路由最终的配置如下,比如home/messageList对应的路由配置保存在<YTRouteractionObject: 0x6040000365e0>对象中

Printing description of self->_routerMap:{ home =  {  "_" = "<YTRouteractionObject: 0x60c00003b040>";  messageList =   {   "_" = "<YTRouteractionObject: 0x6040000365e0>";   detail =    {    "_" = "<YTRouteractionObject: 0x600000038ec0>";   };   getmessage =    {    "_" = "<YTRouteractionObject: 0x600000038e80>";   };  }; };}

路由使用实现

路由使用实现时序图:


如上图所示,步骤很简单:

从注册的配置中找到匹配的YTRouteractionObject对象

执行YTRouteractionObject对象的actionBlock,会传递一个YTRouteractionCallbackObject对象,如果调用者需要的是返回值,可以使用YTRouteractionCallbackObject对象的actionCallbackBlock传递一个返回值,这个actionBlock是又业务方的注册者实现的

以上步骤对应的代码如下:

- (BOol)runWithActionCallbackObject:(YTRouteractionCallbackObject *)actionCallbackObject { // 判断是否支持scheme if (![self canAcceptScheme:actionCallbackObject.uri.scheme]) {  return NO; } // 获取path对应的ActionObject YTRouteractionObject *actionObject = [self actionObjectWithPath:actionCallbackObject.uri.path]; // 执行Path注册的对应Block !actionObject.actionBlock ?: actionObject.actionBlock(actionCallbackObject); return YES;}- (YTRouteractionObject *)actionObjectWithPath:(Nsstring *)path { NSMutableDictionary *subrouter = [self subrouterMapWithPath:path]; return subrouter[YTRouteractionObjectKey];}

客户端的使用

以上讲到了核心的路由注册实现和路由使用实现,总共代码还没有50行,所以还是很简单的,接下来会讲下客户端的使用步骤,包括

客户端注册者注册
客户端调用者使用

客户端注册者注册

注册的时机需要比较找,考虑到集成的方便,选择在load方法中处理路由注册,如下代码所示,添加了几个测试的路由,分两种情况来说明下使用

1、不需要返回值

如下注册"home/messageList"的是一个页面跳转的路由,actionBlock的参数是一个YTRouteractionCallbackObject对象,可以从YTRouteractionCallbackObject对象或者到参数,关于如何传递值,会在下面的客户端调用者使用这里讲到。然后在actionBlock处理目的页面的初始化、参数设置等步骤,然后执行页面跳转。

2、需要返回值

如下注册"home/messageList/getmessage"的是一个提供返回值的路由,同样也可以从YTRouteractionCallbackObject对象获取参数,另外YTRouteractionCallbackObject对象还有一个actionCallbackBlock属性是专门处理返回参数给调用者的,如下的代码只是简单返回一个字符串,在更加具体的业务场景中,这里会设置接口调用、数据库查询等任务,最后把结果返回。

@implementation ModuleAUriRegister+ (voID)load { [[YTRouterManager sharedRouterManager] registerPath:@"home/messageList" actionBlock:^(YTRouteractionCallbackObject *callbackObject) {  MessageListVIEwController *messageListVC = [MessageListVIEwController new];  Nsstring *Title = callbackObject.uri.params[@"Title"];  messageListVC.Title = Title;  [[UIVIEwController yt_currentVIEwControlloer].navigationController pushVIEwController:messageListVC animated:YES];; }]; [[YTRouterManager sharedRouterManager] registerPath:@"home/" actionBlock:^(YTRouteractionCallbackObject *callbackObject) { }]; [[YTRouterManager sharedRouterManager] registerPath:@"home/messageList/detail" actionBlock:^(YTRouteractionCallbackObject *callbackObject) { }]; [[YTRouterManager sharedRouterManager] registerPath:@"home/messageList/getmessage" actionBlock:^(YTRouteractionCallbackObject *callbackObject) {  // 内容回调  !callbackObject.actionCallbackBlock ?: callbackObject.actionCallbackBlock(@"message content text demo"); }];}@end

客户端调用者使用

1、简单的path跳转调用

使用YTRouterManager单例对象的runWithPath方法,传递一个注册的path参数完成跳转。

[self addActionWithTitle:@"Router页面跳转" detailText:@"home/messageList" callback:^{ [[YTRouterManager sharedRouterManager] runWithPath:@"home/messageList"];}];

2、使用URL调用和有URL参数的调用

使用YTRouterManager单例对象的runWithURLString方法,传递一个完整的包含了scheme/path,或者有参数的会才有参数的URL,比如"YTRouter://home/messageList" 和 "YTRouter://home/messageList?Title=Hello Message" ,路由组件会解析出里面的scheme、path、params,进行scheme过滤处理、path查询YTRouteractionObject对象处理、参数传递处理。

[self addActionWithTitle:@"Router使用URL调用" detailText:@"YTRouter://home/messageList" callback:^{ [[YTRouterManager sharedRouterManager] runWithURLString:@"YTRouter://home/messageList"];}];[self addActionWithTitle:@"Router使用带参数的URL调用" detailText:@"YTRouter://home/messageList?Title=Hello Message" callback:^{ [[YTRouterManager sharedRouterManager] runWithURLString:@"YTRouter://home/messageList?Title=Hello Message"];}];

效果如下图所示:


效果图

3、简单的path跳转调用

使用YTRouterManager单例对象的runWithActionCallbackObject方法,传递一个YTRouteractionCallbackObject类型的参数,设置YTRouteractionCallbackObject对象的uri和结果回调actionCallbackBlock参数,在actionCallbackBlock中处理返回值。

[self addActionWithTitle:@"Router获取返回值" detailText:@"home/messageList/getmessage" callback:^{ __block ID message = nil; YTRouteractionCallbackObject *actionCallbackObject = [YTRouteractionCallbackObject new]; actionCallbackObject.uri = [[YTUri alloc] initWithPath:@"home/messageList/getmessage"]; actionCallbackObject.actionCallbackBlock = ^(ID result) {  message = result; }; [[YTRouterManager sharedRouterManager] runWithActionCallbackObject:actionCallbackObject]; NSLog(@"message = %@",message);}];

一些小想法

load方法中注册path对性能有一定的影响,如果这里会成为性能瓶颈,考虑把这部分分代码放在对象方法中初始化,比如主模块发送消息给各个模块,然后在各个模块中处理注册YTRouteractionObject 如果需要更高的细嫩,可以考虑把path参数解析为components进行缓存,这是一种以空间换时间的策略为了提高查找的效率,使用Dictionary而不是数组保存RouteractionObject为了提高查找的效率,使用Dictionary而不是数组保存RouteractionObject

总结

以上所述是小编给大家介绍的iOS使用核心的50行代码撸一个路由组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

总结

以上是内存溢出为你收集整理的iOS使用核心的50行代码撸一个路由组件全部内容,希望文章能够帮你解决iOS使用核心的50行代码撸一个路由组件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1110115.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-29
下一篇2022-05-29

发表评论

登录后才能评论

评论列表(0条)

    保存