diff --git a/lib/ios/RNNBridgeManager.m b/lib/ios/RNNBridgeManager.m index 8ea0d749d0f..ba8aec5d6b0 100644 --- a/lib/ios/RNNBridgeManager.m +++ b/lib/ios/RNNBridgeManager.m @@ -15,6 +15,8 @@ @interface RNNBridgeManager() @property (nonatomic, strong, readwrite) RCTBridge *bridge; @property (nonatomic, strong, readwrite) RNNExternalComponentStore *store; @property (nonatomic, strong, readwrite) RNNReactComponentRegistry *componentRegistry; +@property (nonatomic, strong, readonly) RNNOverlayManager *overlayManager; +@property (nonatomic, strong, readonly) RNNModalManager *modalManager; @end @@ -37,6 +39,9 @@ - (instancetype)initWithJsCodeLocation:(NSURL *)jsCodeLocation launchOptions:(NS _launchOptions = launchOptions; _delegate = delegate; + _overlayManager = [RNNOverlayManager new]; + _modalManager = [RNNModalManager new]; + _store = [RNNExternalComponentStore new]; _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:_launchOptions]; @@ -85,8 +90,8 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { id rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge]; _componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator]; RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentRegistry:_componentRegistry andBridge:bridge]; - - _commandsHandler = [[RNNCommandsHandler alloc] initWithControllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:[RNNOverlayManager new] mainWindow:_mainWindow]; + + _commandsHandler = [[RNNCommandsHandler alloc] initWithControllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:_modalManager overlayManager:_overlayManager mainWindow:_mainWindow]; RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler]; return [@[bridgeModule,eventEmitter] arrayByAddingObjectsFromArray:[self extraModulesFromDelegate]]; @@ -104,7 +109,10 @@ - (void)onJavaScriptLoaded { } - (void)onBridgeWillReload { - UIApplication.sharedApplication.delegate.window.rootViewController = nil; + [_overlayManager dismissAllOverlays]; + [_modalManager dismissAllModalsSynchronosly]; + [_componentRegistry clear]; + UIApplication.sharedApplication.delegate.window.rootViewController = nil; } @end diff --git a/lib/ios/RNNCommandsHandler.m b/lib/ios/RNNCommandsHandler.m index ceecc23cba2..a2d2c3b5d47 100644 --- a/lib/ios/RNNCommandsHandler.m +++ b/lib/ios/RNNCommandsHandler.m @@ -69,7 +69,7 @@ - (void)setRoot:(NSDictionary*)layout commandId:(NSString*)commandId completion: } } - [_modalManager dismissAllModalsAnimated:NO]; + [_modalManager dismissAllModalsAnimated:NO completion:nil]; UIViewController *vc = [_controllerFactory createLayout:layout[@"root"]]; @@ -291,7 +291,7 @@ - (void)dismissAllModals:(NSDictionary *)mergeOptions commandId:(NSString*)comma completion(); }]; RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions]; - [_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES]]; + [_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:nil]; [CATransaction commit]; } diff --git a/lib/ios/RNNModalManager.h b/lib/ios/RNNModalManager.h index 48ff7a9b20f..58011665ccf 100644 --- a/lib/ios/RNNModalManager.h +++ b/lib/ios/RNNModalManager.h @@ -19,6 +19,7 @@ typedef void (^RNNTransitionRejectionBlock)(NSString *code, NSString *message, N - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion; - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion; - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion; -- (void)dismissAllModalsAnimated:(BOOL)animated; +- (void)dismissAllModalsAnimated:(BOOL)animated completion:(void (^ __nullable)(void))completion; +- (void)dismissAllModalsSynchronosly; @end diff --git a/lib/ios/RNNModalManager.m b/lib/ios/RNNModalManager.m index e9b512ac175..d65e4374197 100644 --- a/lib/ios/RNNModalManager.m +++ b/lib/ios/RNNModalManager.m @@ -54,14 +54,27 @@ - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitio } } --(void)dismissAllModalsAnimated:(BOOL)animated { +- (void)dismissAllModalsAnimated:(BOOL)animated completion:(void (^ __nullable)(void))completion { UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController; - [root dismissViewControllerAnimated:animated completion:nil]; + [root dismissViewControllerAnimated:animated completion:completion]; [_delegate dismissedMultipleModals:_presentedModals]; [_pendingModalIdsToDismiss removeAllObjects]; [_presentedModals removeAllObjects]; } +- (void)dismissAllModalsSynchronosly { + if (_presentedModals.count) { + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + [self dismissAllModalsAnimated:NO completion:^{ + dispatch_semaphore_signal(sem); + }]; + + while (dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW)) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]]; + } + } +} + #pragma mark - private diff --git a/lib/ios/RNNOverlayManager.h b/lib/ios/RNNOverlayManager.h index 9b75a09af54..e3e13efa56e 100644 --- a/lib/ios/RNNOverlayManager.h +++ b/lib/ios/RNNOverlayManager.h @@ -7,6 +7,7 @@ - (void)showOverlayWindow:(UIWindow*)viewController; - (void)showOverlayWindowAsKeyWindow:(UIWindow *)overlayWindow; - (void)dismissOverlay:(UIViewController*)viewController; +- (void)dismissAllOverlays; @property (nonatomic, retain) NSMutableArray* overlayWindows; diff --git a/lib/ios/RNNOverlayManager.m b/lib/ios/RNNOverlayManager.m index d3663e7df89..9a007b67b87 100644 --- a/lib/ios/RNNOverlayManager.m +++ b/lib/ios/RNNOverlayManager.m @@ -26,13 +26,19 @@ - (void)showOverlayWindowAsKeyWindow:(RNNOverlayWindow *)overlayWindow { - (void)dismissOverlay:(UIViewController*)viewController { RNNOverlayWindow* overlayWindow = [self findWindowByRootViewController:viewController]; - [overlayWindow.previousWindow makeKeyWindow]; [self detachOverlayWindow:overlayWindow]; } +- (void)dismissAllOverlays { + for (RNNOverlayWindow* overlayWindow in _overlayWindows) { + [self detachOverlayWindow:overlayWindow]; + } +} + #pragma mark - private -- (void)detachOverlayWindow:(UIWindow *)overlayWindow { +- (void)detachOverlayWindow:(RNNOverlayWindow *)overlayWindow { + [overlayWindow.previousWindow makeKeyWindow]; [overlayWindow setHidden:YES]; [overlayWindow setRootViewController:nil]; [_overlayWindows removeObject:overlayWindow]; diff --git a/lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m b/lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m index 1f9df1692db..23b6528e396 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m @@ -51,7 +51,7 @@ - (void)testDismissMultipleModalsInvokeDelegateWithCorrectParameters { [_modalManager showModal:_vc3 animated:NO completion:nil]; _modalManager.delegate = self; - [_modalManager dismissAllModalsAnimated:NO]; + [_modalManager dismissAllModalsAnimated:NO completion:nil]; XCTAssertTrue(_modalDismissedCount == 3); } @@ -87,7 +87,7 @@ - (void)testDismissAllModals_AfterDismissingPreviousModal_InvokeDelegateWithCorr [_modalManager dismissModal:_vc2 completion:nil]; XCTAssertTrue(_modalDismissedCount == 1); - [_modalManager dismissAllModalsAnimated:NO]; + [_modalManager dismissAllModalsAnimated:NO completion:nil]; XCTAssertTrue(_modalDismissedCount == 2); }