iOS 路由改进

2021-04-23  本文已影响0人  赵哥窟

之前写过一篇关于iOS 组件化之CTMediator的文章,小项目中使用起来还是不怎么方便,改进了下,取名为DRouter吧,目录结构是这样的

截屏2021-04-23 15.45.46.png
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 需要跳转的页面。都是动态创建,传参和返回参数的。

下载地址

Demo

上一篇下一篇

猜你喜欢

热点阅读