iOS组件化组件间跳转通讯入门

常见的有三种:
1、URL Scheme
2、CTMediator(Target-Action)
3、Protocol-Class

案例:A页面通过这三种方式跳转B页面


非解耦.png

那么我们需要创建是三个类:Mediator AviewController BviewController

1、URL Scheme

scheme是苹果系统提供的一种供APP之间跳转的机制,用来做组件间跳转也是可行的,这种做法是要全局维护一套scheme和block的映射表,在需要被调用的类(BviewController)中+(void)load方法中注册并实现对应的block,在需要跳转的地方(AviewController)中通过URL来进行跳转并传值
实现:

//********Mediator.h中实现***********
@interface SJMediator : NSObject
//scheme跳转
typedef void(^processBlock)(NSDictionary *params);
+(void)registerScheme:(NSString *)scheme block:(processBlock)block;
+(void)openUrl:(NSString *)url params:(NSDictionary *)params;
@end
//********Mediator.m中实现***********
@implementation SJMediator
//维护的一套全局映射表(字典key:scheme,value:block),全局共用一个,所以使用单例
+ (NSMutableDictionary *)mediatorCache{
    static NSMutableDictionary *cache;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        cache = [NSMutableDictionary dictionary];
    });
    return cache;
}

//scheme注册,被跳转页面+(void)load中实现
+(void)registerScheme:(NSString *)scheme block:(processBlock)block{
    if (scheme && block) {
        [[[self class] mediatorCache] setObject:block forKey:scheme];
    }
}
//跳转页面实现
+(void)openUrl:(NSString *)url params:(NSDictionary *)params{
    //URL可能需要拆分出scheme进行使用,这里简单直接使用,默认URL就是单纯一个scheme
    processBlock block = [[[self class] mediatorCache] objectForKey:url];
    if (block) {
        block(params);
    }
}
@end
//********BviewController.m中实现***********
+ (void)load{
    [SJMediator registerScheme:@"schemeJump://" block:^(NSDictionary *params) {
        BviewController *vc = [[BviewController alloc] init];
        UINavigationController *nav = params[@"nav"];
        [nav pushViewController:vc animated:YES];
    }];
}
//********AviewController.m中点击跳转方法中实现***********
    NSDictionary *params = @{@"nav":self.navigationController};
    [SJMediator openUrl:@"schemeJump://" params:params];
scheme.png

此种方法的总结:
1、需要维护一套映射表,并且注册方法写在+(void)load方法中,在main函数调用之前会走这个方法,会延长APP的启动时间
2、常驻内存,造成资源消耗
3、看似scheme,实则我们看代码中schemeJump://我们可以随便换一个字符串都可以完成跳转,我们使用scheme是为了跟各端统一。用同一套规范就可以实现后端下发scheme,iOS和安卓两端都可以进行跳转
4、跳转的方式是在被跳转页面的load方法block中实现的,所以需要外部传参告诉跳转方式
5、传参方面通过scheme后面拼字符串形式,局限比较大,例如:schemeJump://?token=3jn23e&ID=01

2、CTMediator(Target-Action)

这种方式运用了苹果的运行时
实现:

//********Mediator.h中实现***********
@interface SJMediator : NSObject
//target-action方式
+ (__kindof UIViewController *)getBvcWithContent:(id)content;
@end
//********Mediator.m中实现***********
+ (__kindof UIViewController *)getBvcWithContent:(id)content{
    Class cls = NSClassFromString(@"BviewController");
    //对应的两个object是方法中的两个入参值,根据performSelector的方法来看,最多只能有两个参数,参数可以是任意类型,所以我们尽可能的用字典等集合类型来传参
    UIViewController *vc = [[cls alloc] performSelector:NSSelectorFromString(@"initWithContent:color:") withObject:content withObject:[UIColor colorWithHexString:@"#FF0088"]];
    return vc;
}
//********AviewController.m中点击跳转方法中实现***********
//通过target-action方式跳转详情页
  UIViewController *vc = [SJMediator getBvcWithContent:@"target-action"];
  [self.navigationController pushViewController:vc animated:YES];
//********BviewController.m中实现***********
BviewController中不需要实现其他额外的任何方法
只需要实现自己的initWithContent:color:方法
target_action.png

此种方法的总结:
1、不会入侵被跳转页面,被跳转页面不需要做任何处理
2、跳转方式由外部跳转方决定
3、硬编码多,对于类名和方法名一定要吻合,否则runtime获取不到类型和方法名就会报错,需要做防护处理
4、不需要维护全局映射表
5、传参方面通过字典传内容也相当多了

3、Protocol-Class

此方法与scheme类似,需要维护一个全局映射表(key:Protoc0l,value:Class)
实现:

//********Mediator.h中实现***********
@protocol BViewControllerProtocol 
- (UIViewController *)jumpBvcWithParams:(NSDictionary *_Nullable)params;
@end

@interface SJMediator : NSObject
//protocol协议跳转
+ (void)registerProtocol:(Protocol *)protocol class:(Class)class;
+ (Class)fetchClassForProtocol:(Protocol *)protocol;
@end
//********Mediator.m中实现***********
@implementation SJMediator
+ (NSMutableDictionary *)mediatorCache{
    static NSMutableDictionary *cache;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        cache = [NSMutableDictionary dictionary];
    });
    return cache;
}
//protocol协议跳转
+ (void)registerProtocol:(Protocol *)protocol class:(Class)class{
    if (protocol && class) {
        [[[self class] mediatorCache] setObject:class forKey:NSStringFromProtocol(protocol)];
    }
}
+ (Class)fetchClassForProtocol:(Protocol *)protocol{
    Class cls = [[[self class] mediatorCache] objectForKey:NSStringFromProtocol(protocol)];
    return cls;
}
@end
//********AviewController.m中点击跳转方法中实现***********
//通过protocol_class方式跳转详情页
   Class cls = [SJMediator fetchClassForProtocol:@protocol(BViewControllerProtocol)];
   NSDictionary *params = @{@"color":@"#550088"};
   [self.navigationController pushViewController:[[cls alloc] jumpBvcWithParams:params] animated:YES];
//********BviewController.h中实现***********
注意:继承BViewControllerProtocol协议
//********BviewController.m中实现***********
+ (void)load{
  //注册
    [SJMediator registerProtocal:@protocol(BViewControllerProtocol) class:[self class]];
}

//实现协议方法,创建本类实例
- (UIViewController *)jumpVCWithParams:(NSDictionary * _Nullable)params {
    NSString *colorStr = params[@"color"];
    UIViewController *vc = [[[self class] alloc] init];
    vc.view.backgroundColor = [UIColor colorWithHexString:colorStr];
    return vc;
}
protocol_class.png

此种方法的总结:
1、需要维护一套全局映射表(跟scheme类似)
2、跳转的方式由跳转方处理
3、多了一层protocol
4、传参方面可以传各种类型

本篇只是作为入门,了解三种方式是怎么实现解耦通讯的,通过案例,其实三种利弊也可以看出来,当然还有比较深层次分析的,看这里->组件化方案

你可能感兴趣的:(iOS组件化组件间跳转通讯入门)