// // SPSBRouteManager.m // 我的社保 // // Created by shanp on 2021/4/26. // #import "SPSBRouteManager.h" #import #import "YYClassInfo.h" #import "SPSBBaseNetworkModel.h" #import "SPSBHtmlViewController.h" #import #import #import #import "SPSBGeneralManager.h" #import "SPSBBusinessManager.h" #import "SPSBNavigationController.h" #import "AppDelegate+SPSBRootViewController.h" #import "WXApi.h" #define force_inline __inline__ __attribute__((always_inline)) static force_inline NSNumber *_Nullable spsb_NSNumberCreateFromID(id value) { static NSCharacterSet *dot; static NSDictionary *dic; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ dot = [NSCharacterSet characterSetWithRange:NSMakeRange('.', 1)]; dic = @{@"TRUE" : @(YES), @"True" : @(YES), @"true" : @(YES), @"FALSE" : @(NO), @"False" : @(NO), @"false" : @(NO), @"YES" : @(YES), @"Yes" : @(YES), @"yes" : @(YES), @"NO" : @(NO), @"No" : @(NO), @"no" : @(NO), @"NIL" : (id)kCFNull, @"Nil" : (id)kCFNull, @"nil" : (id)kCFNull, @"NULL" : (id)kCFNull, @"Null" : (id)kCFNull, @"null" : (id)kCFNull, @"(NULL)" : (id)kCFNull, @"(Null)" : (id)kCFNull, @"(null)" : (id)kCFNull, @"" : (id)kCFNull, @"" : (id)kCFNull, @"" : (id)kCFNull}; }); if (!value || value == (id)kCFNull) return nil; if ([value isKindOfClass:[NSNumber class]]) return value; if ([value isKindOfClass:[NSString class]]) { NSNumber *num = dic[value]; if (num != nil) { if (num == (id)kCFNull) return nil; return num; } if ([(NSString *)value rangeOfCharacterFromSet:dot].location != NSNotFound) { const char *cstring = ((NSString *)value).UTF8String; if (!cstring) return nil; double num = atof(cstring); if (isnan(num) || isinf(num)) return nil; return @(num); } else { const char *cstring = ((NSString *)value).UTF8String; if (!cstring) return nil; return @(atoll(cstring)); } } return nil; } @interface SPSBRouter () { NSString *_className; NSDictionary *_property; } @end @implementation SPSBRouter - (instancetype)initWithClassName:(NSString *)className property:(nullable NSDictionary *)property tabBarType:(SPSBTabBarType)tabBarType { self = [super init]; if (!self) return nil; _className = className; _property = property; _spsb_tabBarType = tabBarType; return self; } - (UIViewController *)getTarget { Class class = NSClassFromString(_className); UIViewController *controller = [[class alloc] init]; if (!controller) { return nil; } __block bool canReturn = true; if (!_property) { return controller; } [_property enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([key isKindOfClass:[NSString class]] && [(NSString *)key hasPrefix:@"spsb_"]) { canReturn = [self handleKey:key Value:obj controller:controller class:class]; } }]; if (canReturn) { return controller; } else { return nil; } } - (bool)handleKey:(NSString *)key Value:(id)obj controller:(UIViewController *)controller class:(Class)class { if (![controller canPerformAction:NSSelectorFromString(key) withSender:nil]) { return false;//没有查到类有相关属性 } Class _class = NSClassFromString(_className); while ([NSStringFromClass(_class) hasPrefix:@"SPSB"]) { objc_property_t property = class_getProperty(class, [key UTF8String]); if (property) { YYClassPropertyInfo *info = [[YYClassPropertyInfo alloc] initWithProperty:property]; switch (info.type & YYEncodingTypeMask) { case YYEncodingTypeObject: { if ([info.cls isSubclassOfClass:[SPSBBaseNetworkModel class]]) { if (![obj isKindOfClass:[NSDictionary class]]) { return false;//类型不对 } id object = [info.cls performSelector:@selector(getModelWithDictionary:) withObject:obj]; [controller setValue:object forKey:key]; return true; } else if ([info.cls isSubclassOfClass:[NSString class]]) { if (![obj isKindOfClass:[NSString class]] && ![obj isKindOfClass:[NSNumber class]]) { return false;//类型不对 } [controller setValue:[NSString stringWithFormat:@"%@", obj] forKey:key]; return true; } else if ([info.cls isSubclassOfClass:[NSNumber class]]) { NSNumber *num = spsb_NSNumberCreateFromID(obj); if (!num) { return false;//类型不对 } [controller setValue:num forKey:key]; return true; } else { return false;//不支持类型 } } break; case YYEncodingTypeBool: case YYEncodingTypeInt8: case YYEncodingTypeUInt8: case YYEncodingTypeInt16: case YYEncodingTypeUInt16: case YYEncodingTypeInt32: case YYEncodingTypeUInt32: case YYEncodingTypeInt64: case YYEncodingTypeUInt64: case YYEncodingTypeFloat: case YYEncodingTypeDouble: case YYEncodingTypeLongDouble: { NSNumber *num = spsb_NSNumberCreateFromID(obj); if (!num) { return false;//类型不对 } switch (info.type & YYEncodingTypeMask) { case YYEncodingTypeBool: [controller setValue:num forKey:key]; break; case YYEncodingTypeInt8: case YYEncodingTypeInt16: case YYEncodingTypeInt32: case YYEncodingTypeInt64: [controller setValue:@(num.longLongValue) forKey:key]; break; case YYEncodingTypeUInt8: case YYEncodingTypeUInt16: case YYEncodingTypeUInt32: case YYEncodingTypeUInt64: [controller setValue:@(num.unsignedLongLongValue) forKey:key]; break; case YYEncodingTypeFloat: case YYEncodingTypeDouble: case YYEncodingTypeLongDouble: [controller setValue:@(num.doubleValue) forKey:key]; break; default: break; } return true; } break; default: return false;//不支持类型 break; } } _class = class_getSuperclass(_class); } return false;//没有查到类有相关属性 } @end @implementation SPSBRouteManager + (bool)pageJumpWithData:(NSString *)jump completion:(void (^ _Nullable)(void))completion { if ([jump hasPrefix:@"http"]) { SPSBHtmlViewController *vc = SPSBHtmlViewController.new; vc.spsb_url = jump; return [self routeToTarget:vc isNeedLogin:false isNeedNavi:true completion:completion]; } else if ([jump hasPrefix:@"xsbanruo://"]) { NSDictionary *dic = jxh_getUrlPathAndParameters(jump).jxh_parameters; if (dic[@"iOS"]) { NSString *param = jxh_decode(dic[@"iOS"]); debugLog(@"-=-=-=-=-=-=%@", param); NSMutableDictionary *dict = [jxh_jsonToDictionary(param) mutableCopy]; if (dict[@"page"]) { SPSBRouter *router = [[SPSBRouter alloc] initWithClassName:dict[@"page"] property:dict tabBarType:SPSBTabBarTypeHome]; if (dict[@"needNavi"]) { router.spsb_needNavi = [dict[@"needNavi"] boolValue]; } if (dict[@"needLogin"]) { router.spsb_needLogin = [dict[@"needLogin"] boolValue]; } return [self routeTo:router completion:completion]; } } } else if ([jump hasPrefix:@"miniptogram://"]) { NSString *path = [jump substringFromIndex:14]; WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object]; launchMiniProgramReq.userName = path; //拉起的小程序的username launchMiniProgramReq.miniProgramType = WXMiniProgramTypeRelease; //拉起小程序的类型 [WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) { }]; return false; } return false; } + (bool)routeTo:(SPSBRouter *)router completion:(void (^_Nullable)(void))completion { UIViewController *targetController = [router getTarget]; return [self routeToTarget:targetController isNeedLogin:router.spsb_needLogin isNeedNavi:router.spsb_needNavi completion:completion]; } + (bool)routeToTarget:(UIViewController *)target isNeedLogin:(bool)isNeedLogin isNeedNavi:(bool)isNeedNavi completion:(void (^_Nullable)(void))completion { if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) { if (!target) { return false; } jxh_windowUserInteractionEnabled(false); UIViewController *presentedController = jxh_findPresentedViewControllerStartingFrom(spsb_keyWindow().rootViewController); if (!presentedController) { jxh_windowUserInteractionEnabled(true); return false; } if (isNeedLogin) { jxh_windowUserInteractionEnabled(true); spsb_needLogin(^{ [self routeToTarget:target isNeedLogin:false isNeedNavi:isNeedNavi completion:completion]; }); return true; } if (isNeedNavi) { if ([presentedController isKindOfClass:[UINavigationController class]]) { [(UINavigationController *)presentedController pushViewController:target animated:true]; if (completion) { dispatch_async(dispatch_get_main_queue(), completion); } } else if (presentedController.navigationController) { [presentedController.navigationController pushViewController:target animated:true]; if (completion) { dispatch_async(dispatch_get_main_queue(), completion); } } else { SPSBNavigationController *nav = [[SPSBNavigationController alloc] initWithRootViewController:target]; nav.modalPresentationStyle = UIModalPresentationFullScreen; [presentedController presentViewController:nav animated:true completion:completion]; } } else { [presentedController presentViewController:target animated:true completion:completion]; } jxh_windowUserInteractionEnabled(true); return true; } else { return false; } } + (void)navigationBackAndRouteTo:(SPSBRouter *)router { dispatch_main_async_safe(^{ jxh_windowUserInteractionEnabled(false); [self navigationBackRoot]; [jxh_appDelegate() changeTabBarType:router.spsb_tabBarType]; UIViewController *viewController = [router getTarget]; if (viewController) { [((SPSBNavigationController *)spsb_keyWindow().rootViewController) pushViewController:viewController animated:true]; } jxh_windowUserInteractionEnabled(true); }); } + (void)navigationBackRoot { dispatch_main_async_safe(^{ [self navigationBackLastVC]; }); } + (void)navigationBackLastVC { SPSBNavigationController *rootVC = (SPSBNavigationController *)spsb_keyWindow().rootViewController; if (![rootVC isKindOfClass:[SPSBNavigationController class]]) return; if (rootVC.viewControllers.lastObject.presentedViewController) { [rootVC.viewControllers.lastObject dismissViewControllerAnimated:false completion:^{ [rootVC popToRootViewControllerAnimated:false]; }]; } else { [rootVC popToRootViewControllerAnimated:false]; } // return; // UIViewController *vc = jxh_findPresentedViewControllerStartingFrom(rootVC); // if ([vc isEqual:rootVC.viewControllers.firstObject]) return; // if (vc.navigationController) { // if (vc.navigationController.presentingViewController) { // [vc.navigationController.viewControllers.lastObject dismissViewControllerAnimated:false completion:^{ // [self navigationBackLastVC]; // }]; // } else { // [vc.navigationController popToRootViewControllerAnimated:false]; // dispatch_async(dispatch_get_main_queue(), ^{ // [self navigationBackLastVC]; // }); // // } // } else if (vc.presentingViewController) { // [vc dismissViewControllerAnimated:false completion:^{ // [self navigationBackLastVC]; // }]; // } else { // return; // } } @end