Skip to content

Commit 027299b

Browse files
yogevbdSudoPlz
authored andcommitted
Avoid returning modal that is being dismissed as the top presented viewController (#7644)
This caused a bug in our Wix app when presenting a modal while another one is dismissed. The presented modal was dismissed as well along with the one that was being dismissed.
1 parent 63cf4a8 commit 027299b

File tree

2 files changed

+32
-22
lines changed

2 files changed

+32
-22
lines changed

lib/ios/RNNModalManager.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ - (UIViewController *)rootViewController {
191191

192192
- (UIViewController *)topPresentedVC {
193193
UIViewController *root = [self rootViewController];
194-
while (root.presentedViewController) {
194+
while (root.presentedViewController && !root.presentedViewController.isBeingDismissed) {
195195
root = root.presentedViewController;
196196
}
197197
return root;

playground/ios/NavigationTests/RNNModalManagerTest.m

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ - (void)presentViewController:(UIViewController *)viewControllerToPresent
2121

2222
@end
2323

24-
@interface MockModalManager : RNNModalManager
25-
@property(nonatomic, strong) MockViewController *rootViewController;
26-
@property(nonatomic, strong) MockViewController *topPresentedVC;
27-
@end
28-
29-
@implementation MockModalManager
30-
@end
31-
3224
@interface RNNModalManagerTest : XCTestCase {
3325
CGFloat _modalDismissedCount;
3426
}
@@ -39,7 +31,7 @@ @implementation RNNModalManagerTest {
3931
RNNComponentViewController *_vc1;
4032
RNNComponentViewController *_vc2;
4133
RNNComponentViewController *_vc3;
42-
MockModalManager *_modalManager;
34+
RNNModalManager *_modalManager;
4335
id _modalManagerEventHandler;
4436
}
4537

@@ -53,16 +45,22 @@ - (void)setUp {
5345
_vc3.layoutInfo = [RNNLayoutInfo new];
5446
_modalManagerEventHandler =
5547
[OCMockObject partialMockForObject:[RNNModalManagerEventHandler new]];
56-
_modalManager = [[MockModalManager alloc] initWithBridge:nil
57-
eventHandler:_modalManagerEventHandler];
58-
_modalManager.topPresentedVC = [MockViewController new];
48+
_modalManager = [OCMockObject
49+
partialMockForObject:[[RNNModalManager alloc] initWithBridge:nil
50+
eventHandler:_modalManagerEventHandler]];
51+
52+
UIApplication.sharedApplication.delegate.window.rootViewController =
53+
[OCMockObject partialMockForObject:MockViewController.new];
5954
}
6055

61-
- (void)testDismissMultipleModalsInvokeDelegateWithCorrectParameters {
62-
_modalManager.rootViewController = [OCMockObject partialMockForObject:UIViewController.new];
63-
OCMStub(_modalManager.rootViewController.presentedViewController)
64-
.andReturn(UIViewController.new);
56+
- (void)tearDown {
57+
UIApplication.sharedApplication.delegate.window.rootViewController = UIViewController.new;
58+
}
6559

60+
- (void)testDismissMultipleModalsInvokeDelegateWithCorrectParameters {
61+
OCMStub(
62+
UIApplication.sharedApplication.delegate.window.rootViewController.presentedViewController)
63+
.andReturn(MockViewController.new);
6664
[_modalManager showModal:_vc1 animated:NO completion:nil];
6765
[_modalManager showModal:_vc2 animated:NO completion:nil];
6866
[_modalManager showModal:_vc3 animated:NO completion:nil];
@@ -105,10 +103,9 @@ - (void)testDismissPreviousModal_InvokeDelegateWithCorrectParameters {
105103
}
106104

107105
- (void)testDismissAllModals_AfterDismissingPreviousModal_InvokeDelegateWithCorrectParameters {
108-
_modalManager.rootViewController = [OCMockObject partialMockForObject:UIViewController.new];
109-
OCMStub(_modalManager.rootViewController.presentedViewController)
110-
.andReturn(UIViewController.new);
111-
106+
OCMStub(
107+
UIApplication.sharedApplication.delegate.window.rootViewController.presentedViewController)
108+
.andReturn(MockViewController.new);
112109
[_modalManager showModal:_vc1 animated:NO completion:nil];
113110
[_modalManager showModal:_vc2 animated:NO completion:nil];
114111
[_modalManager showModal:_vc3 animated:NO completion:nil];
@@ -133,8 +130,10 @@ - (void)testShowModal_NilModalThrows {
133130
}
134131

135132
- (void)testShowModal_CallPresentViewController {
133+
OCMStub([_modalManager topPresentedVC]).andReturn([MockViewController new]);
136134
[_modalManager showModal:_vc1 animated:NO completion:nil];
137-
XCTAssertTrue(_modalManager.topPresentedVC.presentViewControllerCalls == 1);
135+
XCTAssertTrue(((MockViewController *)_modalManager.topPresentedVC).presentViewControllerCalls ==
136+
1);
138137
}
139138

140139
- (void)testPresentationControllerDidDismiss_ShouldInvokeDelegateDismissedModal {
@@ -171,4 +170,15 @@ - (void)testApplyOptionsOnInit_shouldShowModalWithDefaultTransitionStyle {
171170
XCTAssertEqual(_vc1.modalTransitionStyle, UIModalTransitionStyleCoverVertical);
172171
}
173172

173+
- (void)testTopPresentedVC_shouldNotReturnModalThatIsBeingDismissed {
174+
UIApplication.sharedApplication.delegate.window.rootViewController =
175+
[OCMockObject partialMockForObject:UIViewController.new];
176+
UIViewController *beingDismissedModal =
177+
[OCMockObject partialMockForObject:[UIViewController new]];
178+
[_modalManager showModal:beingDismissedModal animated:NO completion:nil];
179+
XCTAssertEqual(_modalManager.topPresentedVC, beingDismissedModal);
180+
OCMStub(beingDismissedModal.isBeingDismissed).andReturn(YES);
181+
XCTAssertNotEqual(_modalManager.topPresentedVC, beingDismissedModal);
182+
}
183+
174184
@end

0 commit comments

Comments
 (0)