react-native-navigation的迁移库

RCCManagerModule.m 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #import "RCCManagerModule.h"
  2. #import "RCCManager.h"
  3. #import <UIKit/UIKit.h>
  4. #import "RCCNavigationController.h"
  5. #import "RCCViewController.h"
  6. #import "RCCDrawerController.h"
  7. #import "RCCLightBox.h"
  8. #import "RCTConvert.h"
  9. #import "RCCTabBarController.h"
  10. #import "RCCTheSideBarManagerViewController.h"
  11. #import "RCCNotification.h"
  12. #import "RNNViewController.h"
  13. #define kSlideDownAnimationDuration 0.35
  14. typedef NS_ENUM(NSInteger, RCCManagerModuleErrorCode)
  15. {
  16. RCCManagerModuleCantCreateControllerErrorCode = -100,
  17. RCCManagerModuleCantFindTabControllerErrorCode = -200,
  18. RCCManagerModuleMissingParamsErrorCode = -300
  19. };
  20. @implementation RCTConvert (RCCManagerModuleErrorCode)
  21. RCT_ENUM_CONVERTER(RCCManagerModuleErrorCode,
  22. (@{@"RCCManagerModuleCantCreateControllerErrorCode": @(RCCManagerModuleCantCreateControllerErrorCode),
  23. @"RCCManagerModuleCantFindTabControllerErrorCode": @(RCCManagerModuleCantFindTabControllerErrorCode),
  24. }), RCCManagerModuleCantCreateControllerErrorCode, integerValue)
  25. @end
  26. @implementation RCCManagerModule
  27. RCT_EXPORT_MODULE(RCCManager);
  28. #pragma mark - constatnts export
  29. - (NSDictionary *)constantsToExport
  30. {
  31. return @{
  32. //Error codes
  33. @"RCCManagerModuleCantCreateControllerErrorCode" : @(RCCManagerModuleCantCreateControllerErrorCode),
  34. @"RCCManagerModuleCantFindTabControllerErrorCode" : @(RCCManagerModuleCantFindTabControllerErrorCode),
  35. };
  36. }
  37. - (dispatch_queue_t)methodQueue
  38. {
  39. return dispatch_get_main_queue();
  40. }
  41. #pragma mark - helper methods
  42. +(UIViewController*)modalPresenterViewControllers:(NSMutableArray*)returnAllPresenters
  43. {
  44. UIViewController *modalPresenterViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
  45. if ((returnAllPresenters != nil) && (modalPresenterViewController != nil))
  46. {
  47. [returnAllPresenters addObject:modalPresenterViewController];
  48. }
  49. while (modalPresenterViewController.presentedViewController != nil)
  50. {
  51. modalPresenterViewController = modalPresenterViewController.presentedViewController;
  52. if (returnAllPresenters != nil)
  53. {
  54. [returnAllPresenters addObject:modalPresenterViewController];
  55. }
  56. }
  57. return modalPresenterViewController;
  58. }
  59. +(UIViewController*)lastModalPresenterViewController
  60. {
  61. return [self modalPresenterViewControllers:nil];
  62. }
  63. +(NSError*)rccErrorWithCode:(NSInteger)code description:(NSString*)description
  64. {
  65. NSString *safeDescription = (description == nil) ? @"" : description;
  66. return [NSError errorWithDomain:@"RCCControllers" code:code userInfo:@{NSLocalizedDescriptionKey: safeDescription}];
  67. }
  68. +(void)handleRCTPromiseRejectBlock:(RCTPromiseRejectBlock)reject error:(NSError*)error
  69. {
  70. reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
  71. }
  72. +(void)cancelAllRCCViewControllerReactTouches
  73. {
  74. [[NSNotificationCenter defaultCenter] postNotificationName:RCCViewControllerCancelReactTouchesNotification object:nil];
  75. }
  76. -(void)animateSnapshot:(UIView*)snapshot animationType:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve
  77. {
  78. [UIView animateWithDuration:kSlideDownAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^()
  79. {
  80. if (animationType == nil || [animationType isEqualToString:@"slide-down"])
  81. {
  82. snapshot.transform = CGAffineTransformMakeTranslation(0, snapshot.frame.size.height);
  83. }
  84. else if ([animationType isEqualToString:@"fade"])
  85. {
  86. snapshot.alpha = 0;
  87. }
  88. }
  89. completion:^(BOOL finished)
  90. {
  91. [snapshot removeFromSuperview];
  92. if (resolve != nil)
  93. {
  94. resolve(nil);
  95. }
  96. }];
  97. }
  98. -(void)dismissAllModalPresenters:(NSMutableArray*)allPresentedViewControllers resolver:(RCTPromiseResolveBlock)resolve
  99. {
  100. if (allPresentedViewControllers.count > 0)
  101. {
  102. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
  103. {
  104. __block NSUInteger counter = 0;
  105. for (UIViewController *viewController in allPresentedViewControllers)
  106. {
  107. counter++;
  108. [[RCCManager sharedIntance] unregisterController:viewController];
  109. if (viewController.presentedViewController != nil)
  110. {
  111. dispatch_semaphore_t dismiss_sema = dispatch_semaphore_create(0);
  112. dispatch_async(dispatch_get_main_queue(), ^
  113. {
  114. [viewController dismissViewControllerAnimated:NO completion:^()
  115. {
  116. if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
  117. {
  118. [allPresentedViewControllers removeAllObjects];
  119. if (resolve != nil)
  120. {
  121. resolve(nil);
  122. }
  123. }
  124. dispatch_semaphore_signal(dismiss_sema);
  125. }];
  126. });
  127. dispatch_semaphore_wait(dismiss_sema, DISPATCH_TIME_FOREVER);
  128. }
  129. else if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
  130. {
  131. [allPresentedViewControllers removeAllObjects];
  132. if (resolve != nil)
  133. {
  134. dispatch_async(dispatch_get_main_queue(), ^
  135. {
  136. resolve(nil);
  137. });
  138. }
  139. }
  140. }
  141. });
  142. }
  143. else if (resolve != nil)
  144. {
  145. resolve(nil);
  146. }
  147. }
  148. -(void)startAppHelper:(NSDictionary*)layout
  149. {
  150. [[RCCManager sharedInstance] clearModuleRegistry];
  151. UIViewController *controller = [RNNViewController controllerWithLayout:layout bridge:[[RCCManager sharedInstance] getBridge]];
  152. if (controller == nil) return;
  153. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  154. // set the new controller as the root
  155. appDelegate.window.rootViewController = controller;
  156. [appDelegate.window makeKeyAndVisible];
  157. }
  158. #pragma mark - RCT exported methods
  159. RCT_EXPORT_METHOD(
  160. startApp:(NSDictionary*)layout)
  161. {
  162. if ([[RCCManager sharedInstance] getBridge].loading) {
  163. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  164. [self startAppHelper:layout];
  165. });
  166. return;
  167. }
  168. dispatch_async(dispatch_get_main_queue(), ^{
  169. [self startAppHelper:layout];
  170. });
  171. }
  172. RCT_EXPORT_METHOD(
  173. setRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps)
  174. {
  175. if ([[RCCManager sharedInstance] getBridge].loading) {
  176. [self deferSetRootControllerWhileBridgeLoading:layout animationType:animationType globalProps:globalProps];
  177. return;
  178. }
  179. dispatch_async(dispatch_get_main_queue(), ^{
  180. [self performSetRootController:layout animationType:animationType globalProps:globalProps];
  181. });
  182. }
  183. /**
  184. * on RN31 there's a timing issue, we must wait for the bridge to finish loading
  185. */
  186. -(void)deferSetRootControllerWhileBridgeLoading:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  187. {
  188. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  189. [self setRootController:layout animationType:animationType globalProps:globalProps];
  190. });
  191. }
  192. -(void)performSetRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  193. {
  194. // first clear the registry to remove any refernece to the previous controllers
  195. [[RCCManager sharedInstance] clearModuleRegistry];
  196. // create the new controller
  197. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  198. if (controller == nil) return;
  199. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  200. BOOL animated = !((appDelegate.window.rootViewController == nil) || ([animationType isEqualToString:@"none"]));
  201. // if we're animating - add a snapshot now
  202. UIViewController *presentedViewController = nil;
  203. UIView *snapshot = nil;
  204. if (animated)
  205. {
  206. if(appDelegate.window.rootViewController.presentedViewController != nil)
  207. presentedViewController = appDelegate.window.rootViewController.presentedViewController;
  208. else
  209. presentedViewController = appDelegate.window.rootViewController;
  210. snapshot = [presentedViewController.view snapshotViewAfterScreenUpdates:NO];
  211. [appDelegate.window.rootViewController.view addSubview:snapshot];
  212. }
  213. // dismiss the modal controllers without animation just so they can be released
  214. [self dismissAllControllers:@"none" resolver:^(id result)
  215. {
  216. // set the new controller as the root
  217. appDelegate.window.rootViewController = controller;
  218. [appDelegate.window makeKeyAndVisible];
  219. [presentedViewController dismissViewControllerAnimated:NO completion:nil];
  220. if (animated)
  221. {
  222. // move the snaphot to the new root and animate it
  223. [appDelegate.window.rootViewController.view addSubview:snapshot];
  224. [self animateSnapshot:snapshot animationType:animationType resolver:nil];
  225. }
  226. } rejecter:nil];
  227. }
  228. RCT_EXPORT_METHOD(
  229. NavigationControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  230. {
  231. if (!controllerId || !performAction) return;
  232. RCCNavigationController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"NavigationControllerIOS"];
  233. if (!controller || ![controller isKindOfClass:[RCCNavigationController class]]) return;
  234. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge]];
  235. }
  236. RCT_EXPORT_METHOD(
  237. DrawerControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  238. {
  239. if (!controllerId || !performAction) return;
  240. id<RCCDrawerDelegate> controller = [[RCCManager sharedIntance] getControllerWithId:controllerId componentType:@"DrawerControllerIOS"];
  241. if (!controller || (![controller isKindOfClass:[RCCDrawerController class]] && ![controller isKindOfClass:[RCCTheSideBarManagerViewController class]])) return;
  242. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedIntance] getBridge]];
  243. }
  244. RCT_EXPORT_METHOD(
  245. TabBarControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  246. {
  247. if (!controllerId || !performAction)
  248. {
  249. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  250. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleMissingParamsErrorCode description:@"missing params"]];
  251. return;
  252. }
  253. RCCTabBarController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"TabBarControllerIOS"];
  254. if (!controller || ![controller isKindOfClass:[RCCTabBarController class]])
  255. {
  256. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  257. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantFindTabControllerErrorCode description:@"could not find UITabBarController"]];
  258. return;
  259. }
  260. [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge] completion:^(){ resolve(nil); }];
  261. }
  262. RCT_EXPORT_METHOD(
  263. modalShowLightBox:(NSDictionary*)params)
  264. {
  265. [RCCLightBox showWithParams:params];
  266. }
  267. RCT_EXPORT_METHOD(
  268. modalDismissLightBox)
  269. {
  270. [RCCLightBox dismiss];
  271. }
  272. RCT_EXPORT_METHOD(
  273. showController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  274. {
  275. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  276. if (controller == nil)
  277. {
  278. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  279. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantCreateControllerErrorCode description:@"could not create controller"]];
  280. return;
  281. }
  282. [[RCCManagerModule lastModalPresenterViewController] presentViewController:controller
  283. animated:![animationType isEqualToString:@"none"]
  284. completion:^(){ resolve(nil); }];
  285. }
  286. -(BOOL)viewControllerIsModal:(UIViewController*)viewController
  287. {
  288. BOOL viewControllerIsModal = (viewController.presentingViewController.presentedViewController == viewController)
  289. || ((viewController.navigationController != nil) && (viewController.navigationController.presentingViewController.presentedViewController == viewController.navigationController) && (viewController == viewController.navigationController.viewControllers[0]))
  290. || ([viewController.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]);
  291. return viewControllerIsModal;
  292. }
  293. RCT_EXPORT_METHOD(
  294. dismissController:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  295. {
  296. UIViewController* vc = [RCCManagerModule lastModalPresenterViewController];
  297. if ([self viewControllerIsModal:vc])
  298. {
  299. [[RCCManager sharedIntance] unregisterController:vc];
  300. [vc dismissViewControllerAnimated:![animationType isEqualToString:@"none"]
  301. completion:^(){ resolve(nil); }];
  302. }
  303. }
  304. RCT_EXPORT_METHOD(
  305. dismissAllControllers:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  306. {
  307. if([UIApplication sharedApplication].delegate.window.rootViewController.presentedViewController == nil)
  308. {//if there are no modal - do nothing
  309. resolve(nil);
  310. return;
  311. }
  312. NSMutableArray *allPresentedViewControllers = [NSMutableArray array];
  313. [RCCManagerModule modalPresenterViewControllers:allPresentedViewControllers];
  314. BOOL animated = ![animationType isEqualToString:@"none"];
  315. if (animated)
  316. {
  317. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  318. UIView *snapshot = [appDelegate.window snapshotViewAfterScreenUpdates:NO];
  319. [appDelegate.window addSubview:snapshot];
  320. [self dismissAllModalPresenters:allPresentedViewControllers resolver:^(id result)
  321. {
  322. [self animateSnapshot:snapshot animationType:animationType resolver:resolve];
  323. }];
  324. }
  325. else
  326. {
  327. [self dismissAllModalPresenters:allPresentedViewControllers resolver:resolve];
  328. }
  329. }
  330. RCT_EXPORT_METHOD(
  331. showNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  332. {
  333. [RCCNotification showWithParams:params resolver:resolve rejecter:reject];
  334. }
  335. RCT_EXPORT_METHOD(
  336. dismissNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  337. {
  338. [RCCNotification dismissWithParams:params resolver:resolve rejecter:reject];
  339. }
  340. RCT_EXPORT_METHOD(
  341. cancelAllReactTouches)
  342. {
  343. [RCCManagerModule cancelAllRCCViewControllerReactTouches];
  344. }
  345. @end