JCRoutable
示例
要运行示例项目,请克隆仓库,然后首先从 Example 目录运行 pod install
用法(用法)
-
设置控制器的 URL
[[Routable sharedRouter] map:@"users" toController:[UserController class]];
-
在你的 viewController 中实现 *initWithRouterParams:* 或 + allocWithRouterParams:* 方法
- (id)initWithRouterParams:(NSDictionary *)params { if ((self = [self initWithNibName:nil bundle:nil])) { self.userId = [params objectForKey:@"id"]; } return self; }
// 可用于从storyboard创建的控制器 + (id)allocWithRouterParams:(NSDictionary *)params { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"home" bundle:nil]; FourthViewController *instance = [storyboard instantiateViewControllerWithIdentifier:@"FourthViewController"]; return instance; }
-
跳转到 URL 对应的控制器
[[Routable sharedRouter] open:@"users"];
添加的额外功能
-
添加了一个
批量注册路由
的方法,只需要传入对应的 plist 配置文件路径,新版增加了对从 storyboard 创建控制器
的支持:NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"RoutableConfigure.plist" ofType:nil]; [Routable jc_mapViewControllerToConfigurePlistFile:plistPath];
其中 RoutableConfigure.plist 是控制器 URL 的映射表:
- 普通方式创建的 ViewController:关键为 map 的参数,值为控制器的类名;
- 通过 storyboard 创建的控制器,需要额外的字典描述:
HomeStoryboard
代表一个 storyboard,注意名称必须包含Storyboard
;HomeStoryboardMapKey
对应的值为 storyboard 的真实名称home
;FourthViewControllerMapKey
对应的值为 ViewController 在 storyboard 中的 ID,通常我们设置为和控制器同名FourthViewController
。
最后新建一个 .h 文件,用于定义这些关键:
#ifndef ViewControllersMapKey_h #define ViewControllersMapKey_h static NSString *const JCLoginViewControllerMapKey = @"JCLoginViewControllerMapKey"; static NSString *const ViewControllerMapKey = @"ViewControllerMapKey"; static NSString *const SecondViewControllerMapKey = @"SecondViewControllerMapKey"; static NSString *const ThirdViewControllerMapKey = @"ThirdViewControllerMapKey"; static NSString *const HomeStoryboardMapKey = @"HomeStoryboardMapKey"; #endif /* ViewControllersMapKey_h */
Plist 文件配置不能出错,否则解析会出现问题
-
不需要手动配置 Routable 的 UINavigationController 属性
// 原Routable框架需要手动设置navigationController(JCRoutable不要设置) [[Routable sharedRouter] setNavigationController:aNavigationController];
因为 Routable 本质是通过 UINavigationController 进行 push 或 pop 操作。我们现在分析将 Routable 的 UINavigationController 设置为固定值。
主流 App 架构:
|-> NavigationController1 -> ViewController1 TabBarController -> |-> NavigationController2 -> ViewController2 |-> NavigationController3 -> ViewController3
如果在 *application:didFinishLaunchingWithOptions:* 中将 Routable 的 UINavigationController 设置为固定值,那么 App 架构将变为这样:
|-> NavigationController1 -> ViewController1 Routable.navigationController -> TabBarController -> |-> NavigationController2 -> ViewController2 |-> NavigationController3 -> ViewController3
这样导致 ViewController1、ViewController2、ViewController3 的 navigationItem 被 Routable.navigationController 遮住了。并且 ViewController1 跳转到 ViewController2 不再是由 NavigationController1 控制,而是被 Routable.navigationController 管理,这样导致各个 ViewController 的 navigationItem 设置出现问题。
将 Routable.navigationController 设置为当前所在的控制器,则 App 架构将变为这样:
|-> NavigationController1 -> ViewController1 | Routable.navigationController -> NavigationController1 TabBarController -> |-> NavigationController2 -> ViewController2 | Routable.navigationController -> NavigationController2 |-> NavigationController3 -> ViewController3 | Routable.navigationController -> NavigationController3
当 ViewController1 跳转到 ViewController2 时,我在 Routable 内部执行以下操作:
// 处理navigationController UIViewController *currentController = [UIViewController currentViewController]; if ([currentController isKindOfClass:[UIViewController class]]) { if (currentController.navigationController) { self.navigationController = currentController.navigationController; } else { self.navigationController = [[UINavigationController alloc] init]; } } else if ([currentController isKindOfClass:[UINavigationController class]]) { self.navigationController = (UINavigationController *)currentController; } else { self.navigationController = [[UINavigationController alloc] init]; }
这样 ViewController1 跳转 ViewController2 时,由 NavigationController1 负责;反之 ViewController2 跳转 ViewController1 时,由 NavigationController2 负责。
-
正向传值
原 Routable 正向传值通过
initWithRouterParams:
和allocWithRouterParams:
,如果 ViewController 没有实现这两个方法之一,就会抛出异常,JCRoutable 不强制实现这两个初始化方法,如果需要获取上一个 ViewController 传过来的数据,直接使用self.routerParams
// FirstViewController.m - (void)pushSecondVCAction { [[Routable sharedRouter] open:SecondViewControllerMapKey animated:YES extraParams:@{@"title" : @"routerparamstest"} delegateObject:nil]; }
// SecondViewController.m - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%s, params = %@", __FUNCTION__, self.routerParams); }
-
反向传值
4.1 代理
添加了NSObject+ReverseValue分类,然后在该分类中添加遵守JCReverseValueProtocol协议的属性,只需要导入“Routable.h”文件即可。
// ViewController1 [[Routable sharedRouter] open:@"ViewController2" animated:YES extraParams:@{@"title" : @"come from ViewController1"} delegateObject:self]; - (void)jc_reverseValue:(id)value { NSLog(@"%s:%@", __FUNCTION__, value); }
// ViewController2 if ([self.JCReverseValueDelegate respondsToSelector:@selector(jc_reverseValue:)]) { [self.JCReverseValueDelegate jc_reverseValue:@"(delegate)come from ViewController2"]; }
4.2 块(block)
// ViewController1 [[Routable sharedRouter] open:@"ViewController2" animated:YES extraParams:@{@"title" : @"come from ViewController1"} toCallback:^(NSDictionary *params) { NSLog(@"%s:%@", __FUNCTION__, params); }];
// ViewController2 if (self.callBack) { self.callBack(@{@"params" : @"(block) come from ThirdViewController"}); }
-
用户注销返回登录界面
// 参数为登录界面控制器的类名 [Routable jc_unRegisterAccountToLoginViewController:@"LoginViewController"];
1、反向传值用法请参见demo中的
JCView
和ThirdViewController
; 2、通过storyboard创建控制器的路由注册有两种方式,请参见FourthViewController
和FifthViewController
,以及RoutableConfigure.plist
。
安装(Installation)
JCRoutable可以通过CocoaPods获得。要安装它,只需在Podfile中添加以下行:
pod "JCRoutable"
安装(Installation)
安装(Installation)
安装(Installation)
JCRoutable是在MIT许可下可用的。有关更多信息,请参阅LICENSE文件。