WSRouter—一款轻量级路由跳转框架

简介

大约6个月前,笔者写了一个基于url-block的路由跳转框架,命名为WSRouter。这是一个轻量级框架,仅包含4个.m文件共400多行代码。虽然这个框架很轻,但并不代表其功能不完备,相反,这个框架的功能完全可以应付我们日常的开发需要。无论是对于项目使用还是学习参考,WSRouter都是一个不错的选择。
目前路由跳转方案有很多,大致分为4中:基于URL(url-controller、url-block)的方案、基于target-action的方案、protocol-class方案。本文所说的WSRouter是基于url-block的跳转方案。本文不对这些方案的优缺点进行对比,仅对WSRouter的基本功能和实现做一些简介,欢迎大家使用或star。

原理

基于URL-Controller的路由跳转本质上是有一个路由中介者管理着这些ViewController与URL的映射关系。每一个ViewController都有一个与之对应的URL。每添加一个ViewController我们都要注册一个能够唯一标识这个ViewController的URL到映射表中。如果是基于URL-block的方案,这个映射表中保存的是url-block的关系。当通过URL执行页面转场时,我们通过解析URL中的scheme、host、path。把这3者拼接成scheme://host/path的形式去注册表中查找对应的block或controller(如果是url-block关系,则这个block会返回一个controller)。然后解析URL中的query参数,用query参数配置这个ViewController对象。如果你对URL中的scheme、host、path、query等URL的各个部分不甚了解,下面的例子可以帮助你:

NSURL *url = [NSURL URLWithString:@"ws://www.ws.com/first?uid=999&bid=666"];
id query = url.query;               // uid=999&bid=666
id scheme = url.scheme;             // ws
id host = url.host;                 // www.ws.com
id path = url.path;                 // /first
id absString = url.absoluteString;  // WS://www.ws.com/first?uid=999&bid=666
id absUrl = url.absoluteURL;        // WS://www.ws.com/first?uid=999&bid=666

使用

下面的例子中,先在+(void)load方法中注册了url和block的映射关系。然后调用transferFromViewController:toURL:方法执行跳转。需要注意的是,我们在block的实现中创建了一个对应的控制器实例,然后用URL.query对控制器进行配置。通常,我们将需要传递个目的控制器的参数都拼接到URL.query中

push转场

#import "WSRouter.h"
+ (void)load {
    [self registerRouter];
}

// 注册路由
+ (void)registerRouter {
NSURL *url = [NSURL URLWithString:@"ws://www.ws.com/first"];    
    
    [WSRouter registerRouterWithPrefixURL:url handler:^UIViewController *(NSURL *URL, UIViewController *sourceViewController) {
       // 实例化控制器
        WSPushedViewController *destViewController = [[WSPushedViewController alloc] init];
        // 转场
        [WSRouter transferViewController:destViewController
                      fromViewController:sourceViewController
                              transition:WSTransitionPush];
        destViewController.params = [NSString ws_parameterFromURLQuery:URL.query];
        return destViewController;
    }];
}


// 执行跳转
 [WSRouter transferFromViewController:self
                                   toURL:[NSURL URLWithString:@"WS://www.ws.com/first?uid=666"]];

带回调的转场

还是上面那个例子,有时候我们从目的控制器返回到上一个控制器时,需要执行某些回调,我们仅需要把上例的transferFromViewController:toURL:换成transferFromViewController:toURL:viewWillDisappearCallBack:。这样在页面退出是即可执行回调通知上一个控制器执行一些操作。此外除了viewWillDisappearCallBack之外,WSRouter还支持viewDidDisappearCallBack。其实现使用了Method swizzling。

[WSRouter transferFromViewController:self
                               toURL:[NSURL URLWithString:@"WS://www.ws.com/first?uid=666"]
           viewWillDisappearCallBack:^(UIViewController *destViewController, id callbackData) {
               NSLog(@"%@",callbackData);
           }];

modal转场

如果需要以modal的方式转场,那么仅需要在注册的block中把transition改为WSTransitionPresent即可。如下:

+ (void)registerRouter {
    NSURL *url = [NSURL URLWithString:@"WS://www.ws.com/second"];
    [WSRouter registerRouterWithPrefixURL:url handler:^UIViewController *(NSURL *URL, UIViewController *sourceViewController) {
        UIViewController *destViewController = [[WSPresentedViewController alloc] init];
        [WSRouter transferViewController:destViewController
                      fromViewController:sourceViewController
                              transition:WSTransitionPresent];
        return destViewController;
    }];
}

同一个block跳转不同的页面

值得注意的是,并不是注册一个block只能跳转同一个viewController。我们也可以根据实际情况(比如url中的query参数不同)选择跳转不同的页面,WSRouter也是支持的。但是笔者并不支持这样做。如果我们的工程中存在一个block中根据if...else...语句跳转了不同的页面,那么我们可以考虑对这些不同的页面分开注册。如下:
block中根据query中的web字段是否为ture来区分是否要跳转webViewController。这是一种解决方案,但更好的解决方案是对这两个控制器分开注册。

+ (void)registerRouter {
    // example: url ws://www.ws.com/detail?web=1&uid=999
    NSURL *url = [NSURL URLWithString:@"ws://www.ws.com/third"];
    [WSRouter registerRouterWithPrefixURL:url handler:^UIViewController *(NSURL *URL, UIViewController *sourceViewController) {
        UIViewController *destViewController = nil;
        
        NSDictionary *params = [NSString ws_parameterFromURLQuery:URL.query];
        if ([params[@"web"] boolValue]) {
            destViewController = [[WSWebViewController alloc] init];
        } else {
            destViewController = [[WSPushedViewController alloc] init];
        }
        
        [WSRouter transferViewController:destViewController
                      fromViewController:sourceViewController
                              transition:WSTransitionPush];
        return destViewController;
    }];
}

注意:注册的URL必须是有效的,需要包括scheme、host、path。如果目的控制器需要业务参数,我们还要在跳转URL中携带query部分。

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

推荐阅读更多精彩内容