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

仰天大笑出门去,我辈岂是蓬蒿人。这篇文章主要讲述插件与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]; //paramWPKRouterAction *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的跳转,及路由的关系

文章图片

 
 
【插件与App的跳转,及路由的关系】基础架构
 

    推荐阅读