Sfoglia il codice sorgente

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 anni fa
parent
commit
9970853820
No account linked to committer's email address

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

@@ -15,6 +15,8 @@
15 15
 @property (nonatomic, strong, readwrite) RCTBridge *bridge;
16 16
 @property (nonatomic, strong, readwrite) RNNExternalComponentStore *store;
17 17
 @property (nonatomic, strong, readwrite) RNNReactComponentRegistry *componentRegistry;
18
+@property (nonatomic, strong, readonly) RNNOverlayManager *overlayManager;
19
+@property (nonatomic, strong, readonly) RNNModalManager *modalManager;
18 20
 
19 21
 @end
20 22
 
@@ -37,6 +39,9 @@
37 39
 		_launchOptions = launchOptions;
38 40
 		_delegate = delegate;
39 41
 		
42
+		_overlayManager = [RNNOverlayManager new];
43
+		_modalManager = [RNNModalManager new];
44
+		
40 45
 		_store = [RNNExternalComponentStore new];
41 46
 		_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:_launchOptions];
42 47
 		
@@ -85,8 +90,8 @@
85 90
 	id<RNNComponentViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
86 91
 	_componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator];
87 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 95
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
91 96
 
92 97
 	return [@[bridgeModule,eventEmitter] arrayByAddingObjectsFromArray:[self extraModulesFromDelegate]];
@@ -104,7 +109,10 @@
104 109
 }
105 110
 
106 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 118
 @end

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

@@ -69,7 +69,7 @@ static NSString* const setDefaultOptions	= @"setDefaultOptions";
69 69
 		}
70 70
 	}
71 71
 	
72
-	[_modalManager dismissAllModalsAnimated:NO];
72
+	[_modalManager dismissAllModalsAnimated:NO completion:nil];
73 73
 	
74 74
 	UIViewController *vc = [_controllerFactory createLayout:layout[@"root"]];
75 75
 	
@@ -291,7 +291,7 @@ static NSString* const setDefaultOptions	= @"setDefaultOptions";
291 291
 		completion();
292 292
 	}];
293 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 296
 	[CATransaction commit];
297 297
 }

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

@@ -19,6 +19,7 @@ typedef void (^RNNTransitionRejectionBlock)(NSString *code, NSString *message, N
19 19
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
20 20
 - (void)showModal:(UIViewController *)viewController animated:(BOOL)animated hasCustomAnimation:(BOOL)hasCustomAnimation completion:(RNNTransitionWithComponentIdCompletionBlock)completion;
21 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 25
 @end

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

@@ -54,14 +54,27 @@
54 54
 	}
55 55
 }
56 56
 
57
--(void)dismissAllModalsAnimated:(BOOL)animated {
57
+- (void)dismissAllModalsAnimated:(BOOL)animated completion:(void (^ __nullable)(void))completion {
58 58
 	UIViewController *root = UIApplication.sharedApplication.delegate.window.rootViewController;
59
-	[root dismissViewControllerAnimated:animated completion:nil];
59
+	[root dismissViewControllerAnimated:animated completion:completion];
60 60
 	[_delegate dismissedMultipleModals:_presentedModals];
61 61
 	[_pendingModalIdsToDismiss removeAllObjects];
62 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 78
 #pragma mark - private
66 79
 
67 80
 

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

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

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

@@ -26,13 +26,19 @@
26 26
 
27 27
 - (void)dismissOverlay:(UIViewController*)viewController {
28 28
 	RNNOverlayWindow* overlayWindow = [self findWindowByRootViewController:viewController];
29
-	[overlayWindow.previousWindow makeKeyWindow];
30 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 38
 #pragma mark - private
34 39
 
35
-- (void)detachOverlayWindow:(UIWindow *)overlayWindow {
40
+- (void)detachOverlayWindow:(RNNOverlayWindow *)overlayWindow {
41
+    [overlayWindow.previousWindow makeKeyWindow];
36 42
 	[overlayWindow setHidden:YES];
37 43
 	[overlayWindow setRootViewController:nil];
38 44
 	[_overlayWindows removeObject:overlayWindow];

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

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