Browse Source

Dismiss presented modals and clear the component store on reloading (#5682)

* Dismiss presented modals and clear the component store on reload

* Detach all overlays on react reload

* Move synchronous dismissing modals to modalManager

* Fix iOS unit tests
Yogev Ben David 5 years ago
parent
commit
9970853820
No account linked to committer's email address

+ 11
- 3
lib/ios/RNNBridgeManager.m View File

15
 @property (nonatomic, strong, readwrite) RCTBridge *bridge;
15
 @property (nonatomic, strong, readwrite) RCTBridge *bridge;
16
 @property (nonatomic, strong, readwrite) RNNExternalComponentStore *store;
16
 @property (nonatomic, strong, readwrite) RNNExternalComponentStore *store;
17
 @property (nonatomic, strong, readwrite) RNNReactComponentRegistry *componentRegistry;
17
 @property (nonatomic, strong, readwrite) RNNReactComponentRegistry *componentRegistry;
18
+@property (nonatomic, strong, readonly) RNNOverlayManager *overlayManager;
19
+@property (nonatomic, strong, readonly) RNNModalManager *modalManager;
18
 
20
 
19
 @end
21
 @end
20
 
22
 
37
 		_launchOptions = launchOptions;
39
 		_launchOptions = launchOptions;
38
 		_delegate = delegate;
40
 		_delegate = delegate;
39
 		
41
 		
42
+		_overlayManager = [RNNOverlayManager new];
43
+		_modalManager = [RNNModalManager new];
44
+		
40
 		_store = [RNNExternalComponentStore new];
45
 		_store = [RNNExternalComponentStore new];
41
 		_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:_launchOptions];
46
 		_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:_launchOptions];
42
 		
47
 		
85
 	id<RNNComponentViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
90
 	id<RNNComponentViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
86
 	_componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator];
91
 	_componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator];
87
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentRegistry:_componentRegistry andBridge:bridge];
92
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentRegistry:_componentRegistry andBridge:bridge];
88
-	
89
-	_commandsHandler = [[RNNCommandsHandler alloc] initWithControllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:[RNNOverlayManager new] mainWindow:_mainWindow];
93
+
94
+	_commandsHandler = [[RNNCommandsHandler alloc] initWithControllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:_modalManager overlayManager:_overlayManager mainWindow:_mainWindow];
90
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
95
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
91
 
96
 
92
 	return [@[bridgeModule,eventEmitter] arrayByAddingObjectsFromArray:[self extraModulesFromDelegate]];
97
 	return [@[bridgeModule,eventEmitter] arrayByAddingObjectsFromArray:[self extraModulesFromDelegate]];
104
 }
109
 }
105
 
110
 
106
 - (void)onBridgeWillReload {
111
 - (void)onBridgeWillReload {
107
-	UIApplication.sharedApplication.delegate.window.rootViewController =  nil;
112
+	[_overlayManager dismissAllOverlays];
113
+	[_modalManager dismissAllModalsSynchronosly];
114
+	[_componentRegistry clear];
115
+	UIApplication.sharedApplication.delegate.window.rootViewController = nil;
108
 }
116
 }
109
 
117
 
110
 @end
118
 @end

+ 2
- 2
lib/ios/RNNCommandsHandler.m View File

69
 		}
69
 		}
70
 	}
70
 	}
71
 	
71
 	
72
-	[_modalManager dismissAllModalsAnimated:NO];
72
+	[_modalManager dismissAllModalsAnimated:NO completion:nil];
73
 	
73
 	
74
 	UIViewController *vc = [_controllerFactory createLayout:layout[@"root"]];
74
 	UIViewController *vc = [_controllerFactory createLayout:layout[@"root"]];
75
 	
75
 	
291
 		completion();
291
 		completion();
292
 	}];
292
 	}];
293
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
293
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
294
-	[_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES]];
294
+	[_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:nil];
295
 	
295
 	
296
 	[CATransaction commit];
296
 	[CATransaction commit];
297
 }
297
 }

+ 2
- 1
lib/ios/RNNModalManager.h View File

19
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
19
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
20
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
20
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
21
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion;
21
 - (void)dismissModal:(UIViewController *)viewController completion:(RNNTransitionCompletionBlock)completion;
22
-- (void)dismissAllModalsAnimated:(BOOL)animated;
22
+- (void)dismissAllModalsAnimated:(BOOL)animated completion:(void (^ __nullable)(void))completion;
23
+- (void)dismissAllModalsSynchronosly;
23
 
24
 
24
 @end
25
 @end

+ 15
- 2
lib/ios/RNNModalManager.m View File

54
 	}
54
 	}
55
 }
55
 }
56
 
56
 
57
--(void)dismissAllModalsAnimated:(BOOL)animated {
57
+- (void)dismissAllModalsAnimated:(BOOL)animated completion:(void (^ __nullable)(void))completion {
58
 	UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController;
58
 	UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController;
59
-	[root dismissViewControllerAnimated:animated completion:nil];
59
+	[root dismissViewControllerAnimated:animated completion:completion];
60
 	[_delegate dismissedMultipleModals:_presentedModals];
60
 	[_delegate dismissedMultipleModals:_presentedModals];
61
 	[_pendingModalIdsToDismiss removeAllObjects];
61
 	[_pendingModalIdsToDismiss removeAllObjects];
62
 	[_presentedModals removeAllObjects];
62
 	[_presentedModals removeAllObjects];
63
 }
63
 }
64
 
64
 
65
+- (void)dismissAllModalsSynchronosly {
66
+	if (_presentedModals.count) {
67
+		dispatch_semaphore_t sem = dispatch_semaphore_create(0);
68
+		[self dismissAllModalsAnimated:NO completion:^{
69
+			dispatch_semaphore_signal(sem);
70
+		}];
71
+		
72
+		while (dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW)) {
73
+			[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
74
+		}
75
+	}
76
+}
77
+
65
 #pragma mark - private
78
 #pragma mark - private
66
 
79
 
67
 
80
 

+ 1
- 0
lib/ios/RNNOverlayManager.h View File

7
 - (void)showOverlayWindow:(UIWindow*)viewController;
7
 - (void)showOverlayWindow:(UIWindow*)viewController;
8
 - (void)showOverlayWindowAsKeyWindow:(UIWindow *)overlayWindow;
8
 - (void)showOverlayWindowAsKeyWindow:(UIWindow *)overlayWindow;
9
 - (void)dismissOverlay:(UIViewController*)viewController;
9
 - (void)dismissOverlay:(UIViewController*)viewController;
10
+- (void)dismissAllOverlays;
10
 
11
 
11
 @property (nonatomic, retain) NSMutableArray* overlayWindows;
12
 @property (nonatomic, retain) NSMutableArray* overlayWindows;
12
 
13
 

+ 8
- 2
lib/ios/RNNOverlayManager.m View File

26
 
26
 
27
 - (void)dismissOverlay:(UIViewController*)viewController {
27
 - (void)dismissOverlay:(UIViewController*)viewController {
28
 	RNNOverlayWindow* overlayWindow = [self findWindowByRootViewController:viewController];
28
 	RNNOverlayWindow* overlayWindow = [self findWindowByRootViewController:viewController];
29
-	[overlayWindow.previousWindow makeKeyWindow];
30
 	[self detachOverlayWindow:overlayWindow];
29
 	[self detachOverlayWindow:overlayWindow];
31
 }
30
 }
32
 
31
 
32
+- (void)dismissAllOverlays {
33
+    for (RNNOverlayWindow* overlayWindow  in _overlayWindows) {
34
+        [self detachOverlayWindow:overlayWindow];
35
+    }
36
+}
37
+
33
 #pragma mark - private
38
 #pragma mark - private
34
 
39
 
35
-- (void)detachOverlayWindow:(UIWindow *)overlayWindow {
40
+- (void)detachOverlayWindow:(RNNOverlayWindow *)overlayWindow {
41
+    [overlayWindow.previousWindow makeKeyWindow];
36
 	[overlayWindow setHidden:YES];
42
 	[overlayWindow setHidden:YES];
37
 	[overlayWindow setRootViewController:nil];
43
 	[overlayWindow setRootViewController:nil];
38
 	[_overlayWindows removeObject:overlayWindow];
44
 	[_overlayWindows removeObject:overlayWindow];

+ 2
- 2
lib/ios/ReactNativeNavigationTests/RNNModalManagerTest.m View File

51
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
51
 	[_modalManager showModal:_vc3 animated:NO completion:nil];
52
 	
52
 	
53
 	_modalManager.delegate = self;
53
 	_modalManager.delegate = self;
54
-	[_modalManager dismissAllModalsAnimated:NO];
54
+	[_modalManager dismissAllModalsAnimated:NO completion:nil];
55
 	
55
 	
56
 	XCTAssertTrue(_modalDismissedCount == 3);
56
 	XCTAssertTrue(_modalDismissedCount == 3);
57
 }
57
 }
87
 	[_modalManager dismissModal:_vc2 completion:nil];
87
 	[_modalManager dismissModal:_vc2 completion:nil];
88
 	
88
 	
89
 	XCTAssertTrue(_modalDismissedCount == 1);
89
 	XCTAssertTrue(_modalDismissedCount == 1);
90
-	[_modalManager dismissAllModalsAnimated:NO];
90
+	[_modalManager dismissAllModalsAnimated:NO completion:nil];
91
 	XCTAssertTrue(_modalDismissedCount == 2);
91
 	XCTAssertTrue(_modalDismissedCount == 2);
92
 }
92
 }
93
 
93