陈江川

邮箱:jiangchuanc@gmail.com

使用Routable后的思考

开始接触路由跳转是看了路由跳转的思考这篇文章,本质就是对controller之间跳转解藕的问题。

无论是Android还是iOS,界面之间的跳转必定会带来更高的耦合。所以我在友邻邦这个项目使用Routable管理统跳协议。

但当我在实际开发中使用时,出现了问题:Controller之间如何逆向传值?

Routable提供了ControllerOne跳转到ControllerTwo传值的方法

- (void)open:(NSString *)url
    animated:(BOOL)animated
 extraParams:(NSDictionary *)extraParams;

其中extraParams就是正向传的值,但ControllerTwo反向传值给ControllerOne的方法,Routable并没有提供对应的方法。因此还是必须在ControllerOne中包含ControllerTwo的头文件:

ControllerOne.m

#import "ControllerOne.h"
#import "ControllerTwo.h"

- (void)jumpToControllerTwo {
  ControllerTwo *cTwo = [[ControllerTwo alloc] init];
  cTwo.delegate = self;
  [self.navigationController pushViewController:cTwo animated:YES];
}

这样还是回到了原点,并没有对Controller跳转进行解藕。

如何解决

Controller之间逆向传递数据的方式有三种:delegate、block、Notification,关于这三种方式好坏这里不累赘,个人偏向使用delegate。

  • 选择了delegate,那一定要定义Protocol:
ReverseValueProtocol.h

#import <Foundation/Foundation.h>

@protocol ReverseValueProtocol <NSObject>

@optional

- (void)reverseValue:(id)value;

@end
  • 已经有了Protocol,现在的问题就是在哪里添加遵守Protocol的属性?

    • 一开始想到定一个基础类BasicViewController,再让所有的ViewController继承它; 但是问题又出来了,这个项目已经上架了,等于我要修改项目中所有ViewController文件, 这样很不程序员;
    • 使用Category,写一个UIViewContoller的分类,在该分类中添加遵守Protocol的属性, 然后在Pch文件中包含该分类头文件即可。
    UIViewController+ReverseValue.h
    
    #import <UIKit/UIKit.h>
    #import "ReverseValueProtocol.h"
    
    @interface UIViewController (ReverseValue) <ReverseValueProtocol>
    @property (strong, nonatomic) id<ReverseValueProtocol> delegate;
    @end
    
    UIViewController+ReverseValue.m
    使用Runtime给delegate属性添加getter和setter方法
    
    #import "UIViewController+ReverseValue.h"
    #import <objc/runtime.h>
    
    - (id<ReverseValueProtocol>)delegate {
    return objc_getAssociatedObject(self, @selector(delegate));
    }
    
    - (void)setDelegate:(id<ReverseValueProtocol>)delegate {
    objc_setAssociatedObject(self,
                             @selector(delegate),
                             delegate,
                             OBJC_ASSOCIATION_ASSIGN);
    }
    
    @end
    
  • 最后一个需要解决的,在哪里添加controllerTwo.delegate = controllerOne;

Routable.h添加了一个方法

- (void)open:(NSString *)url
    animated:(BOOL)animated
 extraParams:(NSDictionary *)extraParams
reverseValueProtocol:(BOOL)reverseValue
withViewController:(UIViewController *)viewController;
Routable.m

- (void)open:(NSString *)url
    animated:(BOOL)animated
 extraParams:(NSDictionary *)extraParams
reverseValueProtocol:(BOOL)reverseValue
withViewController:(UIViewController *)viewController {
    
    // 这个方法和open:animated:extraParams:是一样的,我就添加了三行代码
    UIViewController *controller = [self controllerForRouterParams:params];
    
    // add by cjc
    if (reverseValue) {
        controller.delegate = viewController;
    } // end
}

这样就完美的解决了使用Routable逆向传值的问题!另外,比如你要添加delegate方法,只需要在ReverseValueProtocol.h文件声明方法即可!点我Demo地址

« 如何使用BeeHive ReactiveCocoa v2.5学习笔记 »