Skip to content

Commit

Permalink
Fix modal and alert dismissal bugs on iOS (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 f36c67d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 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
5 changes: 4 additions & 1 deletion React/Views/RCTModalHostView.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
@protocol RCTModalHostViewInteractor <NSObject>

- (void)presentModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated;
- (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated;
- (void)dismissModalHostView:(RCTModalHostView *)modalHostView
withViewController:(RCTModalHostViewController *)viewController
animated:(BOOL)animated
completion:(void (^)(void))completionHandler;

@end
8 changes: 6 additions & 2 deletions React/Views/RCTModalHostView.m
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,12 @@ - (void)didUpdateReactSubviews
- (void)dismissModalViewController
{
if (_isPresented) {
[_delegate dismissModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]];
_isPresented = NO;
[_delegate dismissModalHostView:self
withViewController:_modalViewController
animated:[self hasAnimationType]
completion:^{
self->_isPresented = NO;
}];
}
}

Expand Down
13 changes: 11 additions & 2 deletions React/Views/RCTModalHostViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,26 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView withViewControlle
}
}

- (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated
- (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completionHandler
{
dispatch_block_t completionBlock = ^{
if (modalHostView.identifier) {
[[self.bridge moduleForClass:[RCTModalManager class]] modalDismissed:modalHostView.identifier];
}
if (completionHandler) {
completionHandler();
}
};
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 f36c67d

Please sign in to comment.