mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix background access to UIKit in RCTAlertManager (#42684)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42684 This addressed threading issue like this: ``` Attempting to set an overrideUserInterfaceStyle from a background thread. Modifying a view controller from a background thread is not supported ``` Changelog: [iOS][Fixed] Fixed potential threading issues accessing UIKit from background in RCTAlertManager Reviewed By: philIip Differential Revision: D52999194 fbshipit-source-id: 8ce8a89ef932ca9b75cb93d3c9f102a6b0494580
This commit is contained in:
committed by
Facebook GitHub Bot
parent
751eae94d4
commit
8c4979e7a1
@@ -49,9 +49,11 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
for (UIAlertController *alertController in _alertControllers) {
|
||||
[alertController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
RCTExecuteOnMainQueue(^{
|
||||
for (UIAlertController *alertController in self->_alertControllers) {
|
||||
[alertController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,101 +103,100 @@ RCT_EXPORT_METHOD(alertWithArgs : (JS::NativeAlertManager::Args &)args callback
|
||||
}
|
||||
}
|
||||
|
||||
RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title
|
||||
message:nil
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
RCTExecuteOnMainQueue(^{
|
||||
RCTAlertController *alertController = [RCTAlertController alertControllerWithTitle:title
|
||||
message:nil
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIUserInterfaceStyle userInterfaceStyle = [RCTConvert UIUserInterfaceStyle:args.userInterfaceStyle()];
|
||||
alertController.overrideUserInterfaceStyle = userInterfaceStyle;
|
||||
UIUserInterfaceStyle userInterfaceStyle = [RCTConvert UIUserInterfaceStyle:args.userInterfaceStyle()];
|
||||
alertController.overrideUserInterfaceStyle = userInterfaceStyle;
|
||||
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.secureTextEntry = NO;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.secureTextEntry = NO;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleSecureTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Login");
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleSecureTextInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Login");
|
||||
textField.text = defaultValue;
|
||||
textField.keyboardType = keyboardType;
|
||||
}];
|
||||
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
textField.placeholder = RCTUIKitLocalizedString(@"Password");
|
||||
textField.secureTextEntry = YES;
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
break;
|
||||
}
|
||||
|
||||
alertController.message = message;
|
||||
alertController.message = message;
|
||||
|
||||
for (NSDictionary<NSString *, id> *button in buttons) {
|
||||
if (button.count != 1) {
|
||||
RCTLogError(@"Button definitions should have exactly one key.");
|
||||
}
|
||||
NSString *buttonKey = button.allKeys.firstObject;
|
||||
NSString *buttonTitle = [RCTConvert NSString:button[buttonKey]];
|
||||
UIAlertActionStyle buttonStyle = UIAlertActionStyleDefault;
|
||||
if ([buttonKey isEqualToString:cancelButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleCancel;
|
||||
} else if ([buttonKey isEqualToString:destructiveButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleDestructive;
|
||||
}
|
||||
__weak RCTAlertController *weakAlertController = alertController;
|
||||
for (NSDictionary<NSString *, id> *button in buttons) {
|
||||
if (button.count != 1) {
|
||||
RCTLogError(@"Button definitions should have exactly one key.");
|
||||
}
|
||||
NSString *buttonKey = button.allKeys.firstObject;
|
||||
NSString *buttonTitle = [RCTConvert NSString:button[buttonKey]];
|
||||
UIAlertActionStyle buttonStyle = UIAlertActionStyleDefault;
|
||||
if ([buttonKey isEqualToString:cancelButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleCancel;
|
||||
} else if ([buttonKey isEqualToString:destructiveButtonKey]) {
|
||||
buttonStyle = UIAlertActionStyleDestructive;
|
||||
}
|
||||
__weak RCTAlertController *weakAlertController = alertController;
|
||||
|
||||
UIAlertAction *alertAction =
|
||||
[UIAlertAction actionWithTitle:buttonTitle
|
||||
style:buttonStyle
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput:
|
||||
case RCTAlertViewStyleSecureTextInput:
|
||||
callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
NSDictionary<NSString *, NSString *> *loginCredentials = @{
|
||||
@"login" : [weakAlertController.textFields.firstObject text],
|
||||
@"password" : [weakAlertController.textFields.lastObject text]
|
||||
};
|
||||
callback(@[ buttonKey, loginCredentials ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
UIAlertAction *alertAction =
|
||||
[UIAlertAction actionWithTitle:buttonTitle
|
||||
style:buttonStyle
|
||||
handler:^(__unused UIAlertAction *action) {
|
||||
switch (type) {
|
||||
case RCTAlertViewStylePlainTextInput:
|
||||
case RCTAlertViewStyleSecureTextInput:
|
||||
callback(@[ buttonKey, [weakAlertController.textFields.firstObject text] ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
case RCTAlertViewStyleLoginAndPasswordInput: {
|
||||
NSDictionary<NSString *, NSString *> *loginCredentials = @{
|
||||
@"login" : [weakAlertController.textFields.firstObject text],
|
||||
@"password" : [weakAlertController.textFields.lastObject text]
|
||||
};
|
||||
callback(@[ buttonKey, loginCredentials ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
callback(@[ buttonKey ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
}
|
||||
case RCTAlertViewStyleDefault:
|
||||
callback(@[ buttonKey ]);
|
||||
[weakAlertController hide];
|
||||
break;
|
||||
}
|
||||
}];
|
||||
[alertController addAction:alertAction];
|
||||
}];
|
||||
[alertController addAction:alertAction];
|
||||
|
||||
if ([buttonKey isEqualToString:preferredButtonKey]) {
|
||||
[alertController setPreferredAction:alertAction];
|
||||
if ([buttonKey isEqualToString:preferredButtonKey]) {
|
||||
[alertController setPreferredAction:alertAction];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_alertControllers) {
|
||||
_alertControllers = [NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
[_alertControllers addObject:alertController];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!self->_alertControllers) {
|
||||
self->_alertControllers = [NSHashTable weakObjectsHashTable];
|
||||
}
|
||||
[self->_alertControllers addObject:alertController];
|
||||
[alertController show:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user