插件与App的跳转,及路由的关系

Posted tangyuanby2

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插件与App的跳转,及路由的关系相关的知识,希望对你有一定的参考价值。

在SDK中 无法直接跳App 的界面,这个时候需要使用 路由,或者通过 NSClassFromString 的

presentViewController 来跳转。

直接贴代码: 

UIViewController *VC = [NSClassFromString(@"WZFullmotionPagesController") new];

    id prepareAction = ^(void (^ _Nonnull success)(void)) {
        
        UIViewController *VC1 = [NSClassFromString(@"WZServiceSelectController") new];
        id prepareAction1 = ^(void) {
            if (success) success();
        };
        [VC1 setValue:prepareAction1 forKey:@"defaultSetCMCCallBack"];

        [self.navigationController pushViewController:VC1 animated:YES];
        [VC1.view setNeedsDisplay];
    };
    
    [VC setValue:prepareAction forKey:@"prepareAction"];
    [self presentViewController:VC animated:YES completion:nil];

有时候需要回调,可以再回调里 继续添加跳转 

路由的使用:
有的控制器 需要先添加路由的方式,再根据plist 来调用

- (void)router:(WPKRouterAction *)action setParam:(WPKRParamModelBase *)param block:(WPKRouterBlock)block
{
    //这里可以处理逻辑
    NSDictionary *dict = (NSDictionary *)param;
    WPKNameCamSetingController *VC = [[WPKNameCamSetingController alloc] init];
    VC.deviceMac = dict [@"deviceMac"];
    VC.deviceModel = dict [@"deviceModel"];
    VC.nameCamsSetingType = dict[@"nameCamsSetingType"];
    VC.progress = dict[@"progress"];
    VC.saveBtnStr = dict[@"saveBtnStr"];
    VC.routeAddress = dict[@"routeAddress"];
    VC.routeAguments = dict[@"routeAguments"];
    WPKRCallbackModel *callbackModel = [[WPKRCallbackModel alloc] init];
    VC.NameCamSetingFinishClick = ^(NSString * _Nonnull code){
        callbackModel.object = code;
        block(callbackModel);
    };
    [[WPKUIUtils topViewController].navigationController pushViewController:VC animated:YES];

}

路由的具体实现

//
//  WPKRouter.m
//  WZPlatformKit
//
//  Created by abc on 2019/4/30.
//  Copyright © 2019 米家. All rights reserved.
//

#import "WPKRouter.h"
#import "WPKRCallbackModel.h"
#import "WPKRParamModelBase.h"
#import "WPKRouterAction.h"
#import "WPKRouterUtil.h"
#import "WPKSerializationHelper.h"
#import <objc/runtime.h>
#import "WPKRouterPool.h"

//router内部存储actionModel时,给参数增加识别码,用于业务结束操作时回传该识别码,注销actionmodel
static NSString * const WPK_ROUTER_KEY_STRING = @"WPK_ROUTER_KEY_STRING";

static NSString * const WPK_ROUTER_CLASS_PREFIX = @"WPK_router_executor_";
static NSString * const WPK_ROUTER_FUNC_PREFIX = @"retriveSelectorFor_";


typedef void (^WPKRouterH5Block)(WPKRCallbackModel *result, WPKRParamModelBase *modleBase);

@interface WPKRouter() 
@property (atomic, strong) WPKRouterAction *actionModel;

/**
 存储 WPKRouterAction 对象
 */
@property (nonatomic,strong)NSMutableArray * actionModelArray;
@property (nonatomic,strong)NSMutableDictionary * actionModeKeyDic;

@end

@implementation WPKRouter
#pragma mark - life cycles
+ (id)allocWithZone:(struct _NSZone *)zone
{
    return [WPKRouter sharedInstance];
}

+ (instancetype)sharedInstance
{
    static WPKRouter *inst;
    static dispatch_once_t once_t;
    dispatch_once(&once_t, ^{
        inst = [[super allocWithZone:NULL] init];
    });
    return inst;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _util = [[WPKRouterUtil alloc] init];
    }
    return self;
}

#pragma mark - public

- (id)callCls:(NSString *)cls sel:(NSString *)sel params:(NSArray *)params
{
    //    获取类名
    NSString *target = [NSString stringWithFormat:@"%@%@", WPK_ROUTER_CLASS_PREFIX, cls];
    Class c = NSClassFromString(target);
    if (c) {//        获取函数名获取器
        NSString *action = [NSString stringWithFormat:@"%@%@", WPK_ROUTER_FUNC_PREFIX, sel];
        SEL objSel = NSSelectorFromString(action);
        NSObject * obj = [[c alloc] init];
        if ([obj respondsToSelector:objSel]) {
            //            警告!!!此处认为router框架增加的方法固定返回SEL类型,util方法返回字符串
            
            SEL realSel = NSSelectorFromString([WPKRouterUtil performObject:obj selector:objSel withArguments:@[sel]]);
            NSObject *realObj = (NSObject *)[WPKRouterPool excutorForPaths:cls, sel, nil];
            
            //            查看路由池是否有对应的对象
            if (realObj && realSel && [realObj respondsToSelector:realSel]) {
                id res = [WPKRouterUtil performObject:obj selector:realSel withArguments:params];
                return res;
            } else if (realSel && [obj respondsToSelector:realSel]) {
                //路由池无对象则使用新建的子类对象
                id res = [WPKRouterUtil performObject:obj selector:realSel withArguments:params];
                return res;
            } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat"
                WPKInfoLog(@"ERROR: router can‘t find selector: %s", realSel);
#pragma clang diagnostic pop
            }
        } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat"
            WPKInfoLog(@"ERROR: router can‘t find selector: %s", objSel);
#pragma clang diagnostic pop
        }
    }
    return nil;
}

#pragma mark - private
- (void)pushActionModel:(WPKRouterAction*)model routerKey:(NSString *)routerKey
{
    @synchronized(self) {
        if (model.excutor && model.catchCallBack) {
            [self.actionModelArray addObject:model];
            self.actionModeKeyDic[routerKey] = model;
        }
    }
}

- (void)popActionModelWithRouterKey:(NSString *)routerKey
{
    @synchronized(self) {
        WPKRouterAction * model = self.actionModeBlockDic[routerKey];
        if (model.catchCallBack) {
            [self.actionModelArray removeObject:model];
            [self.actionModeKeyDic removeObjectForKey:routerKey];
        }
    }
}

#pragma mark - publics

/**
 *  H5调用WPK协议入口
 *
 *  @param url url
 */
- (void)startUrl:(NSURL *)url
{
    //通过mwap执行参数回调
    WPKRouterH5Block block = ^(WPKRCallbackModel *result, WPKRParamModelBase *modleBase) {
        if (result.object) {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            result.object != nil ? [dict setObject:result.object forKey:@"content"] : nil;
            modleBase.flagId != nil ? [dict setObject:modleBase.flagId forKey:@"flagId"] : nil;
            [[WPKRouter sharedInstance] startModuleSecoupled:@"mwap" path:@"servicecallback" paramDict:dict block:nil];
        }
    };
    [self callNativeFromH5Url:url block:block];
    
}

- (void)startUrl:(NSURL *)url callback:(WPKRouterBlock)callback
{
    WPKRouterH5Block block = ^(WPKRCallbackModel *result, WPKRParamModelBase *modleBase) {
        callback(result);
    };
    [self callNativeFromH5Url:url block:block];
}


//H5专用
- (void)callNativeFromH5Url:(NSURL *)url block:(WPKRouterH5Block)block
{
    NSString *module = [_util getModuleStrFromUrl:url];//module
    NSString *path = [_util getPathStrFromUrl:url];    //path
    NSString *paramStr = [_util getParamStrFromUrl:url];    //param

    WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
    
    if (![actionModel excutor]) {
        [self handleOldVersionWithUrl:url];//兼容老的WPK协议跳转
        return;
    }
    
    if (!module || !path ) {
        WPKRouterBlock temp = ^(WPKRCallbackModel *result) {
            block(result, nil);
        };
        if (path) {
            [_util goto404Error:[module stringByAppendingPathComponent:path] withBlock:temp];
        }
        return;
    }
    
    NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
    
    WPKRParamModelBase*param;
    if ([actionModel.in length] > 0) {
        Class paramClass = NSClassFromString(actionModel.in);
        param = [[paramClass alloc] init];
    } else {
        //h5不设置入参,只需要flagID
        param = [[WPKRParamModelBase alloc] init];
    }
    if ([param isKindOfClass:[WPKRParamModelBase class]]) {
        param.originURL = url;
    }
    [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:param];
    
    WPKRouterBlock blocktemp = ^(WPKRCallbackModel *result) {
        block(result, param);
    };
    [self startModule:module path:path param:param block:blocktemp];
}

- (void)startModule:(NSString *)kWPKRouter_M
              path:(NSString *)kWPKRouter_M_P
             param:(WPKRParamModelBase *)param
             block:(WPKRouterBlock)block
{
    WPKInfoLog(@">> WPKRouter: %@/%@ param: %@",kWPKRouter_M, kWPKRouter_M_P, param );
    WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                            path:kWPKRouter_M_P];
    if (!param) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
        param = [NSObject new];
#pragma clang diagnostic pop
    }
    param.routerKey = [self getDateNow];
    [self pushActionModel:WPKActionModel routerKey:param.routerKey];
    [self handleAction:WPKActionModel paramModel:param block:block];
}

- (void)startModuleSecoupled:(NSString *)kWPKRouter_M
                        path:(NSString *)kWPKRouter_M_P
                   paramDict:(NSDictionary *)paramDict
                       block:(WPKRouterBlock)block
{
    WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                            path:kWPKRouter_M_P];
    WPKActionModel.navigationController = self.navigationController;
    if (!paramDict) {
        paramDict = [NSDictionary new];
    }
    paramDict.routerKey = [self getDateNow];
    [self pushActionModel:WPKActionModel routerKey:paramDict.routerKey];
    WPKRParamModelBase*paramModel;
    if ([WPKActionModel.in length] > 0) {
        Class paramClass = NSClassFromString(WPKActionModel.in);
        paramModel = [[paramClass alloc] init];
    } else {
        //h5不设置入参,只需要flagID
        paramModel = [[WPKRParamModelBase alloc] init];
    }
    
    if ([paramModel respondsToSelector:@selector(analyzeWPKRouterModelWithModelInfo:)]) {
        [paramModel analyzeWPKRouterModelWithModelInfo:paramDict];
    } else if ([paramModel isKindOfClass:[NSDictionary class]]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
        paramModel = paramDict;
#pragma clang diagnostic pop
    } else {
        [[WPKSerializationHelper sharedInstance] importDictionary:paramDict toObject:paramModel];
    }
    /*
     由于 mj_setKeyValues 方法不能将动态添加的属性转到相应的模型中所以进行如此修改
     */
    paramModel.routerKey = paramDict.routerKey;
    [self handleAction:WPKActionModel paramModel:paramModel block:block];
}

- (id)readDataModuleSecoupled:(NSString *)kWPKRouter_M
                         path:(NSString *)kWPKRouter_M_P
                    paramDict:(NSDictionary *)paramDict
{
    WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                            path:kWPKRouter_M_P];
    WPKActionModel.navigationController = self.navigationController;
    if (!paramDict) {
        paramDict = [NSDictionary new];
    }
    paramDict.routerKey = [self getDateNow];
    [self pushActionModel:WPKActionModel routerKey:paramDict.routerKey];
    WPKRParamModelBase*paramModel;
    if ([WPKActionModel.in length] > 0) {
        Class paramClass = NSClassFromString(WPKActionModel.in);
        paramModel = [[paramClass alloc] init];
    } else {
        //h5不设置入参,只需要flagID
        paramModel = [[WPKRParamModelBase alloc] init];
    }
    
    if ([paramModel respondsToSelector:@selector(analyzeWPKRouterModelWithModelInfo:)]) {
        [paramModel analyzeWPKRouterModelWithModelInfo:paramDict];
    } else if ([paramModel isKindOfClass:[NSDictionary class]]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
        paramModel = paramDict;
#pragma clang diagnostic pop
    } else {
        [[WPKSerializationHelper sharedInstance] importDictionary:paramDict toObject:paramModel];
    }
    /*
     由于 mj_setKeyValues 方法不能将动态添加的属性转到相应的模型中所以进行如此修改
     */
    paramModel.routerKey = paramDict.routerKey;
    return [self handleAction:WPKActionModel paramModel:paramModel];
}

- (NSString *)composeURLForModule:(NSString *)kWPKRouter_M
                             path:(NSString *)kWPKRouter_M_P
                            param:(WPKRParamModelBase *)param
                     iswithScheme:(BOOL)isWithScheme {
    
    NSString *json = @"";
    if (param) {
        json = [param toJsonString];
    }
    NSString *scheme = [NSString stringWithFormat:@"%@://", kWPKRouter_scheme];
    NSString *url = [NSString stringWithFormat:@"%@%@/%@?%@=%@",
                     isWithScheme?scheme:@"",
                     kWPKRouter_M,
                     kWPKRouter_M_P?kWPKRouter_M_P:kWPKRouter_default_path,
                     kWPKRouter_paramName,
                     [json stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]
                     ];
    
    return url;
}
/**
 *   解析url数据
 *
 *  @param urlString url
 *
 *  @return 返回地址中存在的参数数据模型
 */
- (nullable WPKRParamModelBase *)parseParamModelWithUrl:(NSString *)urlString;
{
    NSURL *url = [NSURL URLWithString:urlString];
    
    //module
    NSString *module = [_util getModuleStrFromUrl:url];
    if (module == nil) {
        return nil;
    }
    //path
    NSString *path = [_util getPathStrFromUrl:url];
    if (path == nil) {
        return nil;
    }
    //param
    NSString *paramStr = [_util getParamStrFromUrl:url];
    
    WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
    if (paramStr && actionModel.in) {
        NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
        WPKRParamModelBase *model = [(WPKRParamModelBase *) [NSClassFromString(actionModel.in) alloc] init];
        [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:model];
        return model;
    }
    return nil;
}

-(void)callbackAction:(WPKRouterBlock)block result:(id)obj paramIn:(NSObject *)inModel error:(NSError *)error
{
    NSString *key=@"";
    
    if ([inModel.routerKey length] > 0) {
        key = inModel.routerKey;
    }
    if ([self.actionModeBlockDic.allKeys containsObject:key]) {
        [self popActionModelWithRouterKey:key];
    }
    
    WPKRCallbackModel *model = [[WPKRCallbackModel alloc]init];
    if ([obj isKindOfClass:[NSString class]]) {
        model.object = @{@"result":obj};
    } else {
        model.object = obj;
    }
    model.code = (int)error.code;
    model.errorMessage=error.localizedDescription;
    if (block) {
        block(model);
    }
    
}
- (void)callbackAction:(WPKRouterBlock)block result:(id)obj
{
    [self callbackAction:block result:obj paramIn:nil];
}

- (void)callbackAction:(WPKRouterBlock)block result:(id)obj paramIn:(NSObject *)inModel
{
    [self callbackAction:block result:obj paramIn:inModel error:nil];
}

- (BOOL)canCheckModel:(NSString *)kWPKRouter_M path:(NSString *)kWPKRouter_M_P
{
    return [self canCheckModel:[_util getActionFromModule:kWPKRouter_M path:kWPKRouter_M_P]];
}

- (BOOL)canCheckUrl:(NSURL *)url
{
    return [self canCheckModel:[_util getActionFromModule:[_util getModuleStrFromUrl:url] path:[_util getPathStrFromUrl:url]]];
}

- (BOOL)canCheckModel:(WPKRouterAction *)actionModel
{
    if (actionModel == nil || actionModel.excutor.length == 0) {
        return NO;
    }
    
    Class class = NSClassFromString(actionModel.excutor);
    if (class == nil || class == [NSNull null]) {
        return NO;
    }
    
    return YES;
}
#pragma mark - 检测WPK协议是否存在

- (BOOL)startCheckSupportURL:(NSURL *)url
{
    //module
    NSString *module = [_util getModuleStrFromUrl:url];
    //path
    NSString *path = [_util getPathStrFromUrl:url];
    //param
    NSString *paramStr = [_util getParamStrFromUrl:url];
    
    WPKRouterAction *actionModel = [_util getActionFromModule:module path:path];
    WPKRParamModelBase*param;
    if ([actionModel.in length] > 0) {
        Class paramClass = NSClassFromString(actionModel.in);
        param = [[paramClass alloc] init];
    } else {
        //h5不设置入参,只需要flagID
        param = [[WPKRParamModelBase alloc] init];
    }
    
    NSDictionary *paramDic = [_util getParametersDictionaryWithParams:paramStr];
    [[WPKSerializationHelper sharedInstance] importDictionary:paramDic toObject:param];
    
    return [self startCheckSupportModule:module path:path param:param];
}

- (BOOL)startCheckSupportURLString:(NSString *)urlString{
    
    if (!urlString || ![urlString isKindOfClass:[NSString class]] || ![urlString hasPrefix:@"WPK://"]) {
        return NO;
    }
    
    NSURL *url = [NSURL URLWithString:urlString];
    if (!url) {
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//        urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        url = [NSURL URLWithString:urlString];
    }
    
    return [self startCheckSupportURL:url];
}

- (BOOL)startCheckSupportModule:(NSString *)kWPKRouter_M
                           path:(NSString *)kWPKRouter_M_P
                          param:(WPKRParamModelBase*)param
{
    WPKRouterAction *WPKActionModel = [_util getActionFromModule:kWPKRouter_M
                                                            path:kWPKRouter_M_P];
    if (![WPKActionModel excutor]) {
        return NO;
    } else {
        //参数判断
        if ([WPKActionModel.in length] > 0) {
            Class paramClass = NSClassFromString(WPKActionModel.in);
            if (param && ![param isKindOfClass:paramClass]) {
                return NO;
            }
        }
        return YES;
    }
}

#pragma mark - private method

- (void)handleAction:(WPKRouterAction *)action
          paramModel:(NSObject*)paramModel
               block:(WPKRouterBlock)block
{
    if (![action excutor]) {
        [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:block];
    } else {
        if ([paramModel isKindOfClass:[WPKRParamModelBase class]]) {
            action.url = [(WPKRParamModelBase*)paramModel originURL];
        }
        if ([action.in length] > 0) {
            Class paramClass = NSClassFromString(action.in);
            if (paramModel && ![paramModel isKindOfClass:paramClass]) {
                [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:block];
                return;
            }
        }
#pragma clang diagnostic push
#pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
        [action doActionWithParam:paramModel block:block];
#pragma clang diagnostic pop
    }
    
    self.actionModel = action;
}


- (id)handleAction:(WPKRouterAction *)action
          paramModel:(NSObject *)paramModel
{
    self.actionModel = action;
    if (![action excutor]) {
        [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:nil];
    } else {
        if ([paramModel isKindOfClass:[WPKRParamModelBase class]]) {
            action.url = [(WPKRParamModelBase*)paramModel originURL];
        }
        if ([action.in length] > 0) {
            Class paramClass = NSClassFromString(action.in);
            if (paramModel && ![paramModel isKindOfClass:paramClass]) {
                [_util goto404Error:[action.moduleName stringByAppendingPathComponent:action.pathName] withBlock:nil];
                return nil;
            }
        }
#pragma clang diagnostic push
#pragma clang diagnostic ignored  "-Wincompatible-pointer-types"
        return [action doActionWithParam:paramModel];
#pragma clang diagnostic pop
    }
    return nil;
}

#pragma mark - 失败回调

- (void)handleOldVersionWithUrl:(NSURL *)url
{
    /*  WPK://qrcode:1#feedId:o_1462533315926565
     WPK://c-2345
     */
    
    // 浏览器对第二个#进行了混乱解析,
    NSString *newAbsoluteString =  [url.absoluteString stringByReplacingOccurrencesOfString:@"%23" withString:@"#"];
    NSDictionary *dict = @{@"WPKUrl":newAbsoluteString.length?newAbsoluteString:@""};
    [self startModuleSecoupled:@"qrcode" path:@"qrcodeTool" paramDict:dict block:nil];
}

- (NSMutableArray *)actionModelArray
{
    if (!_actionModelArray) {
        _actionModelArray = [NSMutableArray arrayWithCapacity:0];
    }
    if (_actionModelArray.count >= 19) {
        NSArray * keyArr = self.actionModeBlockDic.allKeys;
        for (NSString * key in keyArr) {
            if ([self.actionModeBlockDic[key] isEqual:_actionModelArray.firstObject]) {
                [_actionModelArray removeObject:_actionModelArray.firstObject];
                [self.actionModeBlockDic removeObjectForKey:key];
                break;
            }
        }
    }
    return _actionModelArray;
}

- (NSMutableDictionary *)actionModeBlockDic
{
    if (!_actionModeKeyDic) {
        _actionModeKeyDic = [NSMutableDictionary dictionary];
    }
    return _actionModeKeyDic;
}

- (NSString *)getDateNow
{
    NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
    NSTimeInterval a=[dat timeIntervalSince1970]*1000;
    NSString *timeString = [NSString stringWithFormat:@"%f", a];
    return timeString;
}

@end

@implementation NSObject(WPKRouterExtension)
- (NSString *)routerKey
{
    return objc_getAssociatedObject(self, (__bridge const void *)(WPK_ROUTER_KEY_STRING));
}

- (void)setRouterKey:(NSString *)routerKey
{
    objc_setAssociatedObject(self, (__bridge const void *)(WPK_ROUTER_KEY_STRING), routerKey, OBJC_ASSOCIATION_COPY);
}
@end

App 调用插件代码 及传参

//    [[WPKRouter sharedInstance] startModuleSecoupled:WPK_kPlatformName path:wpk_kNameCamSetting paramDict:@{@"deviceMac":@"2CAA8E21AEC7",@"deviceModel":@"XXXC1-JZ",@"nameCamsSetingType":WPK_Type_bding,@"routeAddress":@"namecamseting",@"progress":@"0.75"} block:^(WPKRCallbackModel *result) {
//    }];

plist文件 设置

技术图片

 

 

基础架构

 

以上是关于插件与App的跳转,及路由的关系的主要内容,如果未能解决你的问题,请参考以下文章

iOS 8以上的设置的跳转

uni-app教程四UniAPP 路由配置及页面跳转

vue路由,二级路由及跳转

3-17 视频讲解路由与导航

前端Vue项目:旅游App-(20)home:点击跳转至带参数的动态路由

APP之间的跳转及参数传递核心方法