SPSBRouteManager.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. //
  2. // SPSBRouteManager.m
  3. // 我的社保
  4. //
  5. // Created by shanp on 2021/4/26.
  6. //
  7. #import "SPSBRouteManager.h"
  8. #import <objc/runtime.h>
  9. #import "YYClassInfo.h"
  10. #import "SPSBBaseNetworkModel.h"
  11. #import "SPSBHtmlViewController.h"
  12. #import <JXHGeneralTools.h>
  13. #import <JXHMacro.h>
  14. #import <JXHSystemShortcut.h>
  15. #import "SPSBGeneralManager.h"
  16. #import "SPSBBusinessManager.h"
  17. #import "SPSBNavigationController.h"
  18. #import "AppDelegate+SPSBRootViewController.h"
  19. #import "WXApi.h"
  20. #define force_inline __inline__ __attribute__((always_inline))
  21. static force_inline NSNumber *_Nullable spsb_NSNumberCreateFromID(id value) {
  22. static NSCharacterSet *dot;
  23. static NSDictionary *dic;
  24. static dispatch_once_t onceToken;
  25. dispatch_once(&onceToken, ^{
  26. dot = [NSCharacterSet characterSetWithRange:NSMakeRange('.', 1)];
  27. dic = @{@"TRUE" : @(YES),
  28. @"True" : @(YES),
  29. @"true" : @(YES),
  30. @"FALSE" : @(NO),
  31. @"False" : @(NO),
  32. @"false" : @(NO),
  33. @"YES" : @(YES),
  34. @"Yes" : @(YES),
  35. @"yes" : @(YES),
  36. @"NO" : @(NO),
  37. @"No" : @(NO),
  38. @"no" : @(NO),
  39. @"NIL" : (id)kCFNull,
  40. @"Nil" : (id)kCFNull,
  41. @"nil" : (id)kCFNull,
  42. @"NULL" : (id)kCFNull,
  43. @"Null" : (id)kCFNull,
  44. @"null" : (id)kCFNull,
  45. @"(NULL)" : (id)kCFNull,
  46. @"(Null)" : (id)kCFNull,
  47. @"(null)" : (id)kCFNull,
  48. @"<NULL>" : (id)kCFNull,
  49. @"<Null>" : (id)kCFNull,
  50. @"<null>" : (id)kCFNull};
  51. });
  52. if (!value || value == (id)kCFNull) return nil;
  53. if ([value isKindOfClass:[NSNumber class]]) return value;
  54. if ([value isKindOfClass:[NSString class]]) {
  55. NSNumber *num = dic[value];
  56. if (num != nil) {
  57. if (num == (id)kCFNull) return nil;
  58. return num;
  59. }
  60. if ([(NSString *)value rangeOfCharacterFromSet:dot].location != NSNotFound) {
  61. const char *cstring = ((NSString *)value).UTF8String;
  62. if (!cstring) return nil;
  63. double num = atof(cstring);
  64. if (isnan(num) || isinf(num)) return nil;
  65. return @(num);
  66. } else {
  67. const char *cstring = ((NSString *)value).UTF8String;
  68. if (!cstring) return nil;
  69. return @(atoll(cstring));
  70. }
  71. }
  72. return nil;
  73. }
  74. @interface SPSBRouter () {
  75. NSString *_className;
  76. NSDictionary *_property;
  77. }
  78. @end
  79. @implementation SPSBRouter
  80. - (instancetype)initWithClassName:(NSString *)className property:(nullable NSDictionary *)property tabBarType:(SPSBTabBarType)tabBarType {
  81. self = [super init];
  82. if (!self) return nil;
  83. _className = className;
  84. _property = property;
  85. _spsb_tabBarType = tabBarType;
  86. return self;
  87. }
  88. - (UIViewController *)getTarget {
  89. Class class = NSClassFromString(_className);
  90. UIViewController *controller = [[class alloc] init];
  91. if (!controller) {
  92. return nil;
  93. }
  94. __block bool canReturn = true;
  95. if (!_property) {
  96. return controller;
  97. }
  98. [_property enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
  99. if ([key isKindOfClass:[NSString class]] && [(NSString *)key hasPrefix:@"spsb_"]) {
  100. canReturn = [self handleKey:key Value:obj controller:controller class:class];
  101. }
  102. }];
  103. if (canReturn) {
  104. return controller;
  105. } else {
  106. return nil;
  107. }
  108. }
  109. - (bool)handleKey:(NSString *)key Value:(id)obj controller:(UIViewController *)controller class:(Class)class {
  110. if (![controller canPerformAction:NSSelectorFromString(key) withSender:nil]) {
  111. return false;//没有查到类有相关属性
  112. }
  113. Class _class = NSClassFromString(_className);
  114. while ([NSStringFromClass(_class) hasPrefix:@"SPSB"]) {
  115. objc_property_t property = class_getProperty(class, [key UTF8String]);
  116. if (property) {
  117. YYClassPropertyInfo *info = [[YYClassPropertyInfo alloc] initWithProperty:property];
  118. switch (info.type & YYEncodingTypeMask) {
  119. case YYEncodingTypeObject: {
  120. if ([info.cls isSubclassOfClass:[SPSBBaseNetworkModel class]]) {
  121. if (![obj isKindOfClass:[NSDictionary class]]) {
  122. return false;//类型不对
  123. }
  124. id object = [info.cls performSelector:@selector(getModelWithDictionary:) withObject:obj];
  125. [controller setValue:object forKey:key];
  126. return true;
  127. } else if ([info.cls isSubclassOfClass:[NSString class]]) {
  128. if (![obj isKindOfClass:[NSString class]] && ![obj isKindOfClass:[NSNumber class]]) {
  129. return false;//类型不对
  130. }
  131. [controller setValue:[NSString stringWithFormat:@"%@", obj] forKey:key];
  132. return true;
  133. } else if ([info.cls isSubclassOfClass:[NSNumber class]]) {
  134. NSNumber *num = spsb_NSNumberCreateFromID(obj);
  135. if (!num) {
  136. return false;//类型不对
  137. }
  138. [controller setValue:num forKey:key];
  139. return true;
  140. } else {
  141. return false;//不支持类型
  142. }
  143. }
  144. break;
  145. case YYEncodingTypeBool:
  146. case YYEncodingTypeInt8:
  147. case YYEncodingTypeUInt8:
  148. case YYEncodingTypeInt16:
  149. case YYEncodingTypeUInt16:
  150. case YYEncodingTypeInt32:
  151. case YYEncodingTypeUInt32:
  152. case YYEncodingTypeInt64:
  153. case YYEncodingTypeUInt64:
  154. case YYEncodingTypeFloat:
  155. case YYEncodingTypeDouble:
  156. case YYEncodingTypeLongDouble: {
  157. NSNumber *num = spsb_NSNumberCreateFromID(obj);
  158. if (!num) {
  159. return false;//类型不对
  160. }
  161. switch (info.type & YYEncodingTypeMask) {
  162. case YYEncodingTypeBool:
  163. [controller setValue:num forKey:key];
  164. break;
  165. case YYEncodingTypeInt8:
  166. case YYEncodingTypeInt16:
  167. case YYEncodingTypeInt32:
  168. case YYEncodingTypeInt64:
  169. [controller setValue:@(num.longLongValue) forKey:key];
  170. break;
  171. case YYEncodingTypeUInt8:
  172. case YYEncodingTypeUInt16:
  173. case YYEncodingTypeUInt32:
  174. case YYEncodingTypeUInt64:
  175. [controller setValue:@(num.unsignedLongLongValue) forKey:key];
  176. break;
  177. case YYEncodingTypeFloat:
  178. case YYEncodingTypeDouble:
  179. case YYEncodingTypeLongDouble:
  180. [controller setValue:@(num.doubleValue) forKey:key];
  181. break;
  182. default:
  183. break;
  184. }
  185. return true;
  186. }
  187. break;
  188. default: return false;//不支持类型
  189. break;
  190. }
  191. }
  192. _class = class_getSuperclass(_class);
  193. }
  194. return false;//没有查到类有相关属性
  195. }
  196. @end
  197. @implementation SPSBRouteManager
  198. + (bool)pageJumpWithData:(NSString *)jump completion:(void (^ _Nullable)(void))completion {
  199. if ([jump hasPrefix:@"http"]) {
  200. SPSBHtmlViewController *vc = SPSBHtmlViewController.new;
  201. vc.spsb_url = jump;
  202. return [self routeToTarget:vc isNeedLogin:false isNeedNavi:true completion:completion];
  203. } else if ([jump hasPrefix:@"xsbanruo://"]) {
  204. NSDictionary *dic = jxh_getUrlPathAndParameters(jump).jxh_parameters;
  205. if (dic[@"iOS"]) {
  206. NSString *param = jxh_decode(dic[@"iOS"]);
  207. debugLog(@"-=-=-=-=-=-=%@", param);
  208. NSMutableDictionary *dict = [jxh_jsonToDictionary(param) mutableCopy];
  209. if (dict[@"page"]) {
  210. SPSBRouter *router = [[SPSBRouter alloc] initWithClassName:dict[@"page"] property:dict tabBarType:SPSBTabBarTypeHome];
  211. if (dict[@"needNavi"]) {
  212. router.spsb_needNavi = [dict[@"needNavi"] boolValue];
  213. }
  214. if (dict[@"needLogin"]) {
  215. router.spsb_needLogin = [dict[@"needLogin"] boolValue];
  216. }
  217. return [self routeTo:router completion:completion];
  218. }
  219. }
  220. } else if ([jump hasPrefix:@"miniptogram://"]) {
  221. NSString *path = [jump substringFromIndex:14];
  222. WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
  223. launchMiniProgramReq.userName = path; //拉起的小程序的username
  224. launchMiniProgramReq.miniProgramType = WXMiniProgramTypeRelease; //拉起小程序的类型
  225. [WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
  226. }];
  227. return false;
  228. }
  229. return false;
  230. }
  231. + (bool)routeTo:(SPSBRouter *)router completion:(void (^_Nullable)(void))completion {
  232. UIViewController *targetController = [router getTarget];
  233. return [self routeToTarget:targetController isNeedLogin:router.spsb_needLogin isNeedNavi:router.spsb_needNavi completion:completion];
  234. }
  235. + (bool)routeToTarget:(UIViewController *)target isNeedLogin:(bool)isNeedLogin isNeedNavi:(bool)isNeedNavi completion:(void (^_Nullable)(void))completion {
  236. if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {
  237. if (!target) {
  238. return false;
  239. }
  240. jxh_windowUserInteractionEnabled(false);
  241. UIViewController *presentedController = jxh_findPresentedViewControllerStartingFrom(spsb_keyWindow().rootViewController);
  242. if (!presentedController) {
  243. jxh_windowUserInteractionEnabled(true);
  244. return false;
  245. }
  246. if (isNeedLogin) {
  247. jxh_windowUserInteractionEnabled(true);
  248. spsb_needLogin(^{
  249. [self routeToTarget:target isNeedLogin:false isNeedNavi:isNeedNavi completion:completion];
  250. });
  251. return true;
  252. }
  253. if (isNeedNavi) {
  254. if ([presentedController isKindOfClass:[UINavigationController class]]) {
  255. [(UINavigationController *)presentedController pushViewController:target animated:true];
  256. if (completion) {
  257. dispatch_async(dispatch_get_main_queue(), completion);
  258. }
  259. } else if (presentedController.navigationController) {
  260. [presentedController.navigationController pushViewController:target animated:true];
  261. if (completion) {
  262. dispatch_async(dispatch_get_main_queue(), completion);
  263. }
  264. } else {
  265. SPSBNavigationController *nav = [[SPSBNavigationController alloc] initWithRootViewController:target];
  266. nav.modalPresentationStyle = UIModalPresentationFullScreen;
  267. [presentedController presentViewController:nav animated:true completion:completion];
  268. }
  269. } else {
  270. [presentedController presentViewController:target animated:true completion:completion];
  271. }
  272. jxh_windowUserInteractionEnabled(true);
  273. return true;
  274. } else {
  275. return false;
  276. }
  277. }
  278. + (void)navigationBackAndRouteTo:(SPSBRouter *)router {
  279. dispatch_main_async_safe(^{
  280. jxh_windowUserInteractionEnabled(false);
  281. [self navigationBackRoot];
  282. [jxh_appDelegate() changeTabBarType:router.spsb_tabBarType];
  283. UIViewController *viewController = [router getTarget];
  284. if (viewController) {
  285. [((SPSBNavigationController *)spsb_keyWindow().rootViewController) pushViewController:viewController animated:true];
  286. }
  287. jxh_windowUserInteractionEnabled(true);
  288. });
  289. }
  290. + (void)navigationBackRoot {
  291. dispatch_main_async_safe(^{
  292. [self navigationBackLastVC];
  293. });
  294. }
  295. + (void)navigationBackLastVC {
  296. SPSBNavigationController *rootVC = (SPSBNavigationController *)spsb_keyWindow().rootViewController;
  297. if (![rootVC isKindOfClass:[SPSBNavigationController class]]) return;
  298. if (rootVC.viewControllers.lastObject.presentedViewController) {
  299. [rootVC.viewControllers.lastObject dismissViewControllerAnimated:false completion:^{
  300. [rootVC popToRootViewControllerAnimated:false];
  301. }];
  302. } else {
  303. [rootVC popToRootViewControllerAnimated:false];
  304. }
  305. // return;
  306. // UIViewController *vc = jxh_findPresentedViewControllerStartingFrom(rootVC);
  307. // if ([vc isEqual:rootVC.viewControllers.firstObject]) return;
  308. // if (vc.navigationController) {
  309. // if (vc.navigationController.presentingViewController) {
  310. // [vc.navigationController.viewControllers.lastObject dismissViewControllerAnimated:false completion:^{
  311. // [self navigationBackLastVC];
  312. // }];
  313. // } else {
  314. // [vc.navigationController popToRootViewControllerAnimated:false];
  315. // dispatch_async(dispatch_get_main_queue(), ^{
  316. // [self navigationBackLastVC];
  317. // });
  318. //
  319. // }
  320. // } else if (vc.presentingViewController) {
  321. // [vc dismissViewControllerAnimated:false completion:^{
  322. // [self navigationBackLastVC];
  323. // }];
  324. // } else {
  325. // return;
  326. // }
  327. }
  328. @end