Skip to content

Commit

Permalink
Fix modal and alert dismissal bugs on iOS [v2] (facebook#22237)
Browse files Browse the repository at this point in the history
  • Loading branch information
sryze committed Oct 13, 2019
1 parent 3a96f4c commit fa3e351
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 8 deletions.
17 changes: 12 additions & 5 deletions React/Modules/RCTAlertManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ @interface RCTAlertManager()
@implementation RCTAlertManager
{
NSHashTable *_alertControllers;
UIWindow *_window;
}

RCT_EXPORT_MODULE()
Expand Down Expand Up @@ -90,11 +91,16 @@ - (void)invalidate
}
}

UIViewController *presentingController = RCTPresentedViewController();
if (presentingController == nil) {
RCTLogError(@"Tried to display alert view but there is no application window. args: %@", args);
return;
}
CGSize screenSize = [UIScreen mainScreen].bounds.size;
self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, screenSize.height)];
#if TARGET_OS_TV
self->_window.windowLevel = UIWindowLevelNormal + 1;
#else
self->_window.windowLevel = UIWindowLevelStatusBar + 1;
#endif
UIViewController *presentingController = [UIViewController new];
self->_window.rootViewController = presentingController;
self->_window.hidden = NO;

UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:title
Expand Down Expand Up @@ -152,6 +158,7 @@ - (void)invalidate
[alertController addAction:[UIAlertAction actionWithTitle:buttonTitle
style:buttonStyle
handler:^(__unused UIAlertAction *action) {
self->_window = nil;
switch (type) {
case RCTAlertViewStylePlainTextInput:
case RCTAlertViewStyleSecureTextInput:
Expand Down
4 changes: 3 additions & 1 deletion React/Views/RCTModalHostView.m
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ - (void)didUpdateReactSubviews
- (void)dismissModalViewController
{
if (_isPresented) {
[_delegate dismissModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]];
[_delegate dismissModalHostView:self
withViewController:_modalViewController
animated:[self hasAnimationType]];
_isPresented = NO;
}
}
Expand Down
22 changes: 20 additions & 2 deletions React/Views/RCTModalHostViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,19 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView withViewControlle
if (_presentationBlock) {
_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock);
} else {
[[modalHostView reactViewController] presentViewController:viewController animated:animated completion:completionBlock];
UIViewController *topViewController = [modalHostView reactViewController];
while (topViewController.presentedViewController != nil) {
if ([topViewController.presentedViewController isKindOfClass:UIAlertController.class]) {
// Don't present on top of UIAlertController, this will mess it up:
// https://stackoverflow.com/questions/27028983/uialertcontroller-is-moved-to-buggy-position-at-top-of-screen-when-it-calls-pre
[topViewController dismissViewControllerAnimated:animated completion:^{
[topViewController presentViewController:viewController animated:animated completion:completionBlock];
}];
return;
}
topViewController = topViewController.presentedViewController;
}
[topViewController presentViewController:viewController animated:animated completion:completionBlock];
}
}

Expand All @@ -89,7 +101,13 @@ - (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewControlle
if (_dismissalBlock) {
_dismissalBlock([modalHostView reactViewController], viewController, animated, completionBlock);
} else {
[viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock];
if (viewController.presentedViewController && viewController.presentingViewController) {
// Ask the presenting view controller to dismiss any view controllers presented on top of the modal host
// together with the host itself.
[viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock];
} else {
[viewController dismissViewControllerAnimated:animated completion:completionBlock];
}
}
}

Expand Down

0 comments on commit fa3e351

Please sign in to comment.