react-native-navigation的迁移库

RNNNavigationStackManager.m 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #import "RNNNavigationStackManager.h"
  2. #import "RNNRootViewController.h"
  3. #import "RNNAnimator.h"
  4. #import "RNNErrorHandler.h"
  5. #import "RNNNavigationController.h"
  6. dispatch_queue_t RCTGetUIManagerQueue(void);
  7. @interface RNNNavigationStackManager()
  8. @property (nonatomic, strong) RNNNavigationController* nvc;
  9. @property (nonatomic, strong) RNNRootViewController* toVC;
  10. @end
  11. @implementation RNNNavigationStackManager {
  12. RNNStore *_store;
  13. RNNTransitionCompletionBlock _completionBlock;
  14. }
  15. -(instancetype)initWithStore:(RNNStore*)store {
  16. self = [super init];
  17. _store = store;
  18. return self;
  19. }
  20. -(void)push:(UIViewController<RNNRootViewProtocol> *)newTop onTop:(NSString *)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
  21. RNNNavigationController *nvc = [self getComponentStack:componentId];
  22. [self assertNavigationControllerExist:nvc reject:rejection];
  23. [self preparePush:newTop onTopVC:nvc completion:completion];
  24. if ([newTop isCustomViewController]) {
  25. [self pushAfterLoad:nil];
  26. } else {
  27. [self waitForContentToAppearAndThen:@selector(pushAfterLoad:)];
  28. }
  29. }
  30. -(void)preparePush:(UIViewController<RNNRootViewProtocol> *)newTop onTopVC:(RNNNavigationController*)nvc completion:(RNNTransitionCompletionBlock)completion {
  31. self.toVC = (RNNRootViewController*)newTop;
  32. self.nvc = nvc;
  33. if (self.toVC.options.animations.push.hasCustomAnimation || self.toVC.isCustomTransitioned) {
  34. nvc.delegate = newTop;
  35. } else {
  36. nvc.delegate = nil;
  37. nvc.interactivePopGestureRecognizer.delegate = nil;
  38. }
  39. _completionBlock = completion;
  40. }
  41. -(void)waitForContentToAppearAndThen:(SEL)nameOfSelector {
  42. [[NSNotificationCenter defaultCenter] addObserver:self
  43. selector:nameOfSelector
  44. name: @"RCTContentDidAppearNotification"
  45. object:nil];
  46. }
  47. -(void)pushAfterLoad:(NSDictionary*)notif {
  48. [[NSNotificationCenter defaultCenter] removeObserver:self name:@"RCTContentDidAppearNotification" object:nil];
  49. [CATransaction begin];
  50. [CATransaction setCompletionBlock:^{
  51. if (_completionBlock) {
  52. _completionBlock();
  53. _completionBlock = nil;
  54. }
  55. }];
  56. [self.nvc pushViewController:self.toVC animated:self.toVC.options.animations.push.enable];
  57. [CATransaction commit];
  58. self.toVC = nil;
  59. self.nvc.interactivePopGestureRecognizer.delegate = nil;
  60. self.nvc = nil;
  61. }
  62. -(void)pop:(NSString *)componentId withTransitionOptions:(RNNAnimationOptions *)transitionOptions rejection:(RCTPromiseRejectBlock)rejection {
  63. RNNRootViewController* vc = (RNNRootViewController*)[_store findComponentForId:componentId];
  64. UINavigationController* nvc = [self getComponentStack:componentId];
  65. [self assertNavigationControllerExist:nvc reject:rejection];
  66. if ([nvc topViewController] == vc) {
  67. if (vc.options.animations.pop) {
  68. nvc.delegate = vc;
  69. [nvc popViewControllerAnimated:vc.options.animations.pop.enable];
  70. } else {
  71. nvc.delegate = nil;
  72. [nvc popViewControllerAnimated:vc.options.animations.pop.enable];
  73. }
  74. } else {
  75. NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
  76. [vcs removeObject:vc];
  77. [nvc setViewControllers:vcs animated:vc.options.animations.pop.enable];
  78. }
  79. [_store removeComponent:componentId];
  80. }
  81. -(void)popTo:(NSString*)componentId rejection:(RCTPromiseRejectBlock)rejection {
  82. RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
  83. RNNNavigationController *nvc = [self getComponentStack:componentId];
  84. [self assertNavigationControllerExist:nvc reject:rejection];
  85. if (vc && nvc) {
  86. NSArray *poppedVCs = [nvc popToViewController:vc animated:vc.options.animations.pop.enable];
  87. [self removePopedViewControllers:poppedVCs];
  88. }
  89. }
  90. -(void)popToRoot:(NSString*)componentId rejection:(RCTPromiseRejectBlock)rejection {
  91. RNNRootViewController *vc = (RNNRootViewController*)[_store findComponentForId:componentId];
  92. RNNNavigationController *nvc = [self getComponentStack:componentId];
  93. [self assertNavigationControllerExist:nvc reject:rejection];
  94. NSArray* poppedVCs = [nvc popToRootViewControllerAnimated:vc.options.animations.pop.enable];
  95. [self removePopedViewControllers:poppedVCs];
  96. }
  97. -(void)setStackRoot:(UIViewController<RNNRootViewProtocol> *)newRoot fromComponent:(NSString *)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
  98. RNNNavigationController* nvc = [self getComponentStack:componentId];
  99. [self assertNavigationControllerExist:nvc reject:rejection];
  100. [CATransaction begin];
  101. [CATransaction setCompletionBlock:^{
  102. if (completion) {
  103. completion();
  104. }
  105. }];
  106. [nvc setViewControllers:@[newRoot] animated:newRoot.options.animations.push.enable];
  107. [CATransaction commit];
  108. }
  109. - (void)assertNavigationControllerExist:(UINavigationController *)viewController reject:(RCTPromiseRejectBlock)reject {
  110. if (![viewController isKindOfClass:[UINavigationController class]]) {
  111. _completionBlock = nil;
  112. [RNNErrorHandler reject:reject withErrorCode:RNNCommandErrorCodeNoStack errorDescription:[NSString stringWithFormat:@"%@ should be called from a stack child component", [RNNErrorHandler getCallerFunctionName]]];
  113. }
  114. }
  115. - (RNNNavigationController*)getComponentStack:(NSString *)componentId {
  116. UIViewController* component = [_store findComponentForId:componentId];
  117. if ([component isKindOfClass:[UINavigationController class]]) {
  118. return (RNNNavigationController*)component;
  119. } else {
  120. return (RNNNavigationController*)component.navigationController;
  121. }
  122. }
  123. -(void)removePopedViewControllers:(NSArray*)viewControllers {
  124. for (UIViewController *popedVC in viewControllers) {
  125. [_store removeComponentByViewControllerInstance:popedVC];
  126. }
  127. }
  128. @end