iOS Router原理篇

前言:

iOS强调模块化、组件化,讲究模块内高内聚,模块间低耦合。
那么模块与模块之间的低耦合,就要求模块间的通信要尽可能的减少依赖,SDRouter,就是这样的中间产物。

SDRouter的设计是参照一水流年的想法来实现的,总体和他的想法保持一致,但是会更加的简洁、易用,作者设计的拓展性强,但是依赖过多,导致库不太容易单独存在。那么,你可以看到使用该库,可以使用URL的方式打开任何Native页面,如下面一个伪协议:asone://oneController?title=as_one
asone是AppSchema.完全按照http协议涉及的跳转,让该库SDRouter的结构简单,想法也简单。

先设想一下:如何从AController以URL的方式跳转到BController并携带参数?

先看下SDRouter中是怎么实现的:

- (void)viewDidLoad {
    [super viewDidLoad];
//  在页面上添加一个button
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 100, 80)];
    [button setTitle:@"one" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(go) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

//  点击跳转到下一个控制器 并携带下一个控制器的标题
- (void)go {
    NSDictionary *param = @{@"title":@"as_one"};
    NSURL *url = SDURLRouteQueryLink(OneController, param);
    [[SDRouter shareRutor] rutor:url];
}

再设想一下:如何从BController以OpenUrl的方式打开CController并传递参数?

//  先忽略+load方法中的内容
+ (void)load {
    [[SDRouter shareRutor] addPaten:OneController callback:^(SDRouterContext *context) {
        NSLog(@"优品财富: %@",context.paramters);
        OneViewController *textOneVc = [[OneViewController alloc] init];
        textOneVc.navigationItem.title = context.paramters[@"title"];
        [context.topNavigationController pushViewController:textOneVc animated:YES];
    }];
}

//  先看这里
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithRed:((float)arc4random_uniform(256) / 255.0) green:((float)arc4random_uniform(256) / 255.0) blue:((float)arc4random_uniform(256) / 255.0) alpha:1.0];
    //  页面上添加一个按钮
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 100, 80)];
    [button setTitle:@"openUrl" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(openUrl) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
}
//  点击调转,以openUrl的方式打开一个控制器并携带参数,该参数是navigationTitle。
- (void)openUrl {
    NSDictionary *dict = @{@"title":@"as_two"};
    NSURL *url = SDURLRouteQueryLink(TwoController, dict);
    [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {}];
}

最后再想一下,H5怎么快捷的打开CController并携带参数?

//  H5页面添加一个按钮并添加js跳转
<input class="class1 class2" type="button" value="跳转到as_Three页面" style="width:500px;height:150px;font-size:40px"onclick=javascrtpt:jump()>
function jump(){
    window.location="asone://threeController?title=as😝three";
}

上面三种设想可以参看下图:

hello1.gif

SDRouter设计思想:

  • URL部分:看似URL跳转,实际上是对URL的解析、组合编解码。
    SDRouterUtil主要包含了对URL的解析及组合编解码的方法。
@interface NSString (SDURLEncode)
- (NSString *)URLEncode;
- (NSString *)URLDecode;
@end
//  用来处理参数携带 拼接参数 返回编码、拼接后的URL
FOUNDATION_EXTERN NSURL *SDURLRouteQueryLink(NSString *baseUrl, NSDictionary *query);

//  添加参数
FOUNDATION_EXTERN NSString *SDURLRouteJoinParamterString(NSString *urlStr, NSString *query);

//  将拼接好的参数encode
FOUNDATION_EXTERN NSString *SDURLRouteEncodeURLQueryParamters(NSDictionary *paramter);

//  将参数decode
FOUNDATION_EXTERN NSDictionary *SDURLRouteDecodeURLQueryParamters(NSString *urlStr);
  • 跳转:
    URL拼接好,从AController跳转到BController,跳转的方法其实很简单。
    [[SDRouter shareRutor] rutor:url];那这句代码又做了什么呢?重点看这段代码
+ (void)load {
    [[SDRouter shareRutor] addPaten:OneController callback:^(SDRouterContext *context) {
        NSLog(@"优品财富: %@",context.paramters);
        OneViewController *textOneVc = [[OneViewController alloc] init];
        textOneVc.navigationItem.title = context.paramters[@"title"];
        [context.topNavigationController pushViewController:textOneVc animated:YES];
    }];
}

在SDRouter中提供了一个注册的方法,必须在load方法中注册,+load是已知的执行最早的方法,比main函数好要早,这里不做过多解释,不明白可以参看你真的了解+load方法吗?
addPaten:OneController其实这个oneController是定义的字符串常量,如:asone://oneController?title=as_one,在App启动后,SDRouter会记录当前这个控制器和所携带的callback

//  实现比较简单
- (void)addPaten:(NSString *)paten callback:(SDCompleteCallback)callback{
    NSDictionary *dict = @{paten:callback};
    if (![_results containsObject:dict]) {
        [_results addObject:dict];
    }
}

在调用[[SDRouter shareRutor] rutor:url]的时候,会匹配需要前往的url。

- (void)rutor:(NSURL *)paten {
    SDURLParser *parser = [[SDURLParser alloc] initWithURL:paten];
    [_results enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([[obj allKeys].firstObject isEqualToString:parser.paten]) {
            SDRouterContext *context = [[SDRouterContext alloc] init];
            context.paramters = parser.paramters;
            if ([obj allValues].firstObject) {
                SDCompleteCallback callback = (SDCompleteCallback)[obj allValues].firstObject;
                callback(context);
            }
            *stop = YES;
        }
    }];
}
  • push
    到这里,已经能够保证在+load方法中获取到参数,重点是页面怎么push出来。因为+load方法执行时,是不能够获取到navigationController的,那么怎么获取到并push呢?

  • 全局UI栈
    其实一开始并没有该类,但是通过其他方式获取总是觉的鸡肋,还是通过一水文章的点拨才有了该类。
    该类中利用runtime方法替换,重写Controller的生命周期方法,声明一个指针数组,在viewWillApear的时候加入UI栈,在disWill的时候移除UI栈,参数的携带和栈顶控制器的携带,是通过SDContext来完成的。该类中包含了参数及navigation。

讲解比较粗略,想了解的可以到demo中查看。
github

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

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,121评论 29 470
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 那条林荫大道 首发:沐遥诗雨(MoyleSY) 作者:李沐遥 . 秋寒乍起,秋叶簌簌 铺一地锦绣 落一场金灿灿的雨...
    李沐遥阅读 253评论 2 2
  • 金庸和古龙,共同打造了一个武侠世界。在这个武侠世界里,有爱恨情仇,有江湖恩怨门派斗争。 金庸的人物内...
    张小白在努力阅读 435评论 0 0
  • 阳春三月,四处弥漫着一种“叫春的气息”,单身的弟弟妹妹们纷纷扎入爱河,一发不可收拾。找到一个理想的如意郎君或如意娇...
    婷不下来ing阅读 300评论 0 0