From 11df4cb08ce49014f01d0d26679f4ad736e33735 Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Thu, 5 Nov 2015 03:49:41 -0800 Subject: [PATCH] Fixed display of alerts on top of modal window Reviewed By: javache Differential Revision: D2616170 fb-gh-sync-id: f72f728008099fff6fc966d7a2ce4c0d27a4fefd --- .../ActionSheetIOS/RCTActionSheetManager.m | 6 ++--- Libraries/CameraRoll/RCTImagePickerManager.m | 12 +++------ React/Base/RCTUtils.h | 4 +++ React/Base/RCTUtils.m | 25 +++++++++++++------ React/Modules/RCTAlertManager.m | 2 +- React/Modules/RCTDevMenu.m | 2 +- 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Libraries/ActionSheetIOS/RCTActionSheetManager.m b/Libraries/ActionSheetIOS/RCTActionSheetManager.m index 841292bc3..626da966c 100644 --- a/Libraries/ActionSheetIOS/RCTActionSheetManager.m +++ b/Libraries/ActionSheetIOS/RCTActionSheetManager.m @@ -66,7 +66,7 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions:(NSDictionary *)options NSInteger destructiveButtonIndex = options[@"destructiveButtonIndex"] ? [RCTConvert NSInteger:options[@"destructiveButtonIndex"]] : -1; NSInteger cancelButtonIndex = options[@"cancelButtonIndex"] ? [RCTConvert NSInteger:options[@"cancelButtonIndex"]] : -1; - UIViewController *controller = RCTSharedApplication().delegate.window.rootViewController; + UIViewController *controller = RCTKeyWindow().rootViewController; if (controller == nil) { RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", options); return; @@ -166,7 +166,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options } UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; - UIViewController *controller = RCTSharedApplication().delegate.window.rootViewController; + UIViewController *controller = RCTKeyWindow().rootViewController; #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 @@ -212,8 +212,6 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options } else { RCTLogWarn(@"No callback registered for action sheet: %@", actionSheet.title); } - - [RCTSharedApplication().delegate.window makeKeyWindow]; } @end diff --git a/Libraries/CameraRoll/RCTImagePickerManager.m b/Libraries/CameraRoll/RCTImagePickerManager.m index c778c1f48..d6f8846c0 100644 --- a/Libraries/CameraRoll/RCTImagePickerManager.m +++ b/Libraries/CameraRoll/RCTImagePickerManager.m @@ -60,8 +60,7 @@ RCT_EXPORT_METHOD(openCameraDialog:(NSDictionary *)config return; } - UIWindow *keyWindow = RCTSharedApplication().keyWindow; - UIViewController *rootViewController = keyWindow.rootViewController; + UIViewController *rootViewController = RCTKeyWindow().rootViewController; UIImagePickerController *imagePicker = [UIImagePickerController new]; imagePicker.delegate = self; @@ -87,8 +86,7 @@ RCT_EXPORT_METHOD(openSelectDialog:(NSDictionary *)config return; } - UIWindow *keyWindow = RCTSharedApplication().keyWindow; - UIViewController *rootViewController = keyWindow.rootViewController; + UIViewController *rootViewController = RCTKeyWindow().rootViewController; UIImagePickerController *imagePicker = [UIImagePickerController new]; imagePicker.delegate = self; @@ -121,8 +119,7 @@ didFinishPickingMediaWithInfo:(NSDictionary *)info [_pickerCallbacks removeObjectAtIndex:index]; [_pickerCancelCallbacks removeObjectAtIndex:index]; - UIWindow *keyWindow = RCTSharedApplication().keyWindow; - UIViewController *rootViewController = keyWindow.rootViewController; + UIViewController *rootViewController = RCTKeyWindow().rootViewController; [rootViewController dismissViewControllerAnimated:YES completion:nil]; callback(@[[info[UIImagePickerControllerReferenceURL] absoluteString]]); @@ -137,8 +134,7 @@ didFinishPickingMediaWithInfo:(NSDictionary *)info [_pickerCallbacks removeObjectAtIndex:index]; [_pickerCancelCallbacks removeObjectAtIndex:index]; - UIWindow *keyWindow = RCTSharedApplication().keyWindow; - UIViewController *rootViewController = keyWindow.rootViewController; + UIViewController *rootViewController = RCTKeyWindow().rootViewController; [rootViewController dismissViewControllerAnimated:YES completion:nil]; callback(@[]); diff --git a/React/Base/RCTUtils.h b/React/Base/RCTUtils.h index de25e3728..02e37c8b9 100644 --- a/React/Base/RCTUtils.h +++ b/React/Base/RCTUtils.h @@ -58,6 +58,10 @@ RCT_EXTERN BOOL RCTRunningInAppExtension(void); // Returns the shared UIApplication instance, or nil if running in an App Extension RCT_EXTERN UIApplication *RCTSharedApplication(void); +// Returns the current main window, useful if you need to access the root view +// or view controller, e.g. to present a modal view controller or alert. +RCT_EXTERN UIWindow *RCTKeyWindow(void); + // Return a UIAlertView initialized with the given values // or nil if running in an app extension RCT_EXTERN UIAlertView *RCTAlertView(NSString *title, diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index f59577d79..afc865de4 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -342,26 +342,35 @@ BOOL RCTRunningInAppExtension(void) return [[[[NSBundle mainBundle] bundlePath] pathExtension] isEqualToString:@"appex"]; } -id RCTSharedApplication(void) +UIApplication *RCTSharedApplication(void) { if (RCTRunningInAppExtension()) { return nil; } - return [[UIApplication class] performSelector:@selector(sharedApplication)]; } -id RCTAlertView(NSString *title, - NSString *message, - id delegate, - NSString *cancelButtonTitle, - NSArray *otherButtonTitles) +UIWindow *RCTKeyWindow(void) +{ + if (RCTRunningInAppExtension()) { + return nil; + } + + // TODO: replace with a more robust solution + return RCTSharedApplication().keyWindow; +} + +UIAlertView *RCTAlertView(NSString *title, + NSString *message, + id delegate, + NSString *cancelButtonTitle, + NSArray *otherButtonTitles) { if (RCTRunningInAppExtension()) { RCTLogError(@"RCTAlertView is unavailable when running in an app extension"); return nil; } - + UIAlertView *alertView = [UIAlertView new]; alertView.title = title; alertView.message = message; diff --git a/React/Modules/RCTAlertManager.m b/React/Modules/RCTAlertManager.m index 992ef25ca..7c6ef18f5 100644 --- a/React/Modules/RCTAlertManager.m +++ b/React/Modules/RCTAlertManager.m @@ -89,7 +89,7 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args return; } - UIViewController *presentingController = RCTSharedApplication().delegate.window.rootViewController; + UIViewController *presentingController = RCTKeyWindow().rootViewController; if (presentingController == nil) { RCTLogError(@"Tried to display alert view but there is no application window. args: %@", args); return; diff --git a/React/Modules/RCTDevMenu.m b/React/Modules/RCTDevMenu.m index 2da16ccb4..acad8b1da 100644 --- a/React/Modules/RCTDevMenu.m +++ b/React/Modules/RCTDevMenu.m @@ -454,7 +454,7 @@ RCT_EXPORT_METHOD(show) actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1; actionSheet.actionSheetStyle = UIBarStyleBlack; - [actionSheet showInView:RCTSharedApplication().keyWindow.rootViewController.view]; + [actionSheet showInView:RCTKeyWindow().rootViewController.view]; _actionSheet = actionSheet; _presentedItems = items; }