JCRoutable 0.1.9

JCRoutable 0.1.9

JCTransition 维护。



  • By
  • chenjiangchuan

JCRoutable

Version License Platform

示例

要运行示例项目,请克隆仓库,然后首先从 Example 目录运行 pod install

用法(用法)

  1. 设置控制器的 URL

    [[Routable sharedRouter] map:@"users" toController:[UserController class]];
    
  2. 在你的 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;
    }
    
  3. 跳转到 URL 对应的控制器

    [[Routable sharedRouter] open:@"users"];
    

添加的额外功能

  1. 添加了一个 批量注册路由 的方法,只需要传入对应的 plist 配置文件路径,新版增加了对 从 storyboard 创建控制器 的支持:

    NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"RoutableConfigure.plist" ofType:nil];
    [Routable jc_mapViewControllerToConfigurePlistFile:plistPath];
    

    其中 RoutableConfigure.plist 是控制器 URL 的映射表:

    1. 普通方式创建的 ViewController:关键为 map 的参数,值为控制器的类名;
    2. 通过 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 文件配置不能出错,否则解析会出现问题

  1. 不需要手动配置 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 负责。

  2. 正向传值

    原 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);
    }
    
  3. 反向传值

    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"});
    }
    
  4. 用户注销返回登录界面

    // 参数为登录界面控制器的类名
    [Routable jc_unRegisterAccountToLoginViewController:@"LoginViewController"];
    

1、反向传值用法请参见demo中的JCViewThirdViewController; 2、通过storyboard创建控制器的路由注册有两种方式,请参见FourthViewControllerFifthViewController,以及RoutableConfigure.plist

安装(Installation)

JCRoutable可以通过CocoaPods获得。要安装它,只需在Podfile中添加以下行:

pod "JCRoutable"

安装(Installation)

安装(Installation)

安装(Installation)

JCRoutable是在MIT许可下可用的。有关更多信息,请参阅LICENSE文件。