iOS 路由改进
2021-04-23 本文已影响0人
赵哥窟
之前写过一篇关于iOS 组件化之CTMediator的文章,小项目中使用起来还是不怎么方便,改进了下,取名为DRouter吧,目录结构是这样的
DRouter
这个两个文件就不说了,就是CTMediator源文件改下名字,代码是一样的
Target_Commons
看代码就知道就是动态添加参数和回调的,CTMediator是在每个Module下面都添加一个Target_xxxx,这样觉得麻烦就写一个通用的。
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString * const DRouterTargetCommons;
@interface Target_Commons : NSObject
// 自定义push方法
- (UIViewController *)Action_Push_CommonController:(NSDictionary *)params;
@end
NS_ASSUME_NONNULL_END
#import "Target_Commons.h"
#import "UIViewController+Parameter.h"
#import "UIViewController+Block.h"
#import <objc/runtime.h>
typedef void (^callBlock)(NSDictionary *);
NSString * const DRouterTargetCommons = @"Commons";
@implementation Target_Commons
// 自定义push方法
- (UIViewController *)Action_Push_CommonController:(NSDictionary *)params{
NSString *vcClassName = params[@"vcClassName"];
callBlock callback = params[@"callback"];
Class class = NSClassFromString(vcClassName);
UIViewController *controller = [[class alloc] init];
//传值
if([params objectForKey:@"vauleParameter"] != nil){
controller.parameter = [params objectForKey:@"vauleParameter"];
}
//参数回调
if(callback != nil){
controller.backBlock = ^(NSDictionary * _Nonnull parameter) {
callback(parameter);
};
}
return controller;
}
@end
UIViewController+Parameter
分类给Controller添加参数用的
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIViewController (Parameter)
@property (copy, nonatomic) NSDictionary *parameter;
@end
NS_ASSUME_NONNULL_END
#import "UIViewController+Parameter.h"
#import <objc/runtime.h>
static const char * PARAMETER_KEY = "parameter_key";
@implementation UIViewController (Parameter)
- (void)setParameter:(NSDictionary *)parameter{
objc_setAssociatedObject(self, PARAMETER_KEY, parameter, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSDictionary *)parameter {
return objc_getAssociatedObject(self, PARAMETER_KEY);
}
@end
UIViewController+Block
给Controller添加回调用的
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^BackBlock)(NSDictionary *parameter);
@interface UIViewController (Block)
/** 完成的回调block */
@property (nonatomic, copy) BackBlock backBlock;
@end
NS_ASSUME_NONNULL_END
#import "UIViewController+Block.h"
#import <objc/runtime.h>
static const char * BLOCK_KEY = "block_key";
@implementation UIViewController (Block)
- (void)setBackBlock:(BackBlock)backBlock{
objc_setAssociatedObject(self, BLOCK_KEY, backBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (BackBlock)backBlock {
return objc_getAssociatedObject(self, BLOCK_KEY);
}
@end
具体使用
截屏2021-04-23 15.52.38.png如果图,每个Module还是新建一个Mediator
#import "DRouter.h"
NS_ASSUME_NONNULL_BEGIN
@interface DRouter (A_Module)
- (UIViewController *)mediator_AModulePage1:(NSMutableDictionary *)params;
- (UIViewController *)mediator_AModulePage1:(NSMutableDictionary *)params completion:(void (^)(NSDictionary *))completion;
@end
NS_ASSUME_NONNULL_END
#import "DRouter+A_Module.h"
// 字符串 是类名 Target_xxx.h 中的 xxx 部分
NSString * const kMediatorTarget_A_Module = @"A_Module";
@implementation DRouter (A_Module)
- (UIViewController *)mediator_AModulePage1:(NSMutableDictionary *)params{
UIViewController *viewController = [self performTarget:@"Commons"
action:@"Action_Push_CommonController"
params:params shouldCacheTarget:NO];
if ([viewController isKindOfClass:[UIViewController class]]) {
// view controller 交付出去之后,可以由外界选择是push还是present
return viewController;
} else {
// 这里处理异常场景,具体如何处理取决于产品
NSLog(@"%@ 未能实例化页面", NSStringFromSelector(_cmd));
return [[UIViewController alloc] init];
}
}
- (UIViewController *)mediator_AModulePage1:(NSMutableDictionary *)params completion:(void (^)(NSDictionary *))completion{
[params setValue:completion forKey:@"callback"];
return [self mediator_AModulePage1:params];
}
@end
Controller中使用
- (void)pushAModulePage1
{
NSMutableDictionary *param = [NSMutableDictionary dictionary];
[param setValue:@"APage1Controller" forKey:@"vcClassName"];
//需要回调时添加
[param setValue:@"callback" forKey:@"callback"];
//需要传值是添加
[param setValue:@{@"value":@"我是上一个页面传过来的value"} forKey:@"vauleParameter"];
UIViewController *viewController = [[DRouter sharedInstance]mediator_AModulePage1:param completion:^(NSDictionary * _Nonnull dic) {
[self showAlert:[dic objectForKey:@"value"]];
}];
[self.navigationController pushViewController:viewController animated:YES];
}
返回参数
- (IBAction)blockAction:(UIButton *)sender {
if(self.backBlock){
[self.navigationController popViewControllerAnimated:YES];
self.backBlock(@{@"value":@"A_Module_Page1_Block"});
}else{
[self.navigationController popViewControllerAnimated:YES];
}
}
可以看到,我们在跳转并没有#import 需要跳转的页面。都是动态创建,传参和返回参数的。