Fix Alert memory leak

Summary:
1. Using weak container to hold the currently opened alerts.
2. Using weak reference to alertController in action handler block.
3. BTW,  remove the unused vars: _alertCallbacks, _alertButtonKeys.

Test plan (required)

```
- (void)invalidate
{
  for (UIAlertController *alertController in _alertControllers) {
    [alertController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
  }
}
```
Since we use weak container, _alertControllers should only contains the currently opened alerts.

I test this way: Put a breakpoint in invalidate, open the UIExplorer play with the 'Alert' & 'AlertIOS' examples, then fire a reload and see if _alertControllers contains the expected values.
Closes https://github.com/facebook/react-native/pull/10407

Differential Revision: D4078649

Pulled By: lacker

fbshipit-source-id: 8509e7e7142379a81d5b28c9067c085bad8bb5cb
This commit is contained in:
littlesome 2016-10-25 17:17:19 -07:00 committed by Facebook Github Bot
parent d932c96ddc
commit 49667db1c8

View File

@ -31,9 +31,7 @@ RCT_ENUM_CONVERTER(RCTAlertViewStyle, (@{
@implementation RCTAlertManager
{
NSMutableArray<UIAlertController *> *_alertControllers;
NSMutableArray<RCTResponseSenderBlock> *_alertCallbacks;
NSMutableArray<NSArray<NSString *> *> *_alertButtonKeys;
NSHashTable *_alertControllers;
}
RCT_EXPORT_MODULE()
@ -148,18 +146,19 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
} else if ([buttonKey isEqualToString:destructiveButtonKey]) {
buttonStyle = UIAlertActionStyleDestructive;
}
__weak UIAlertController *weakAlertController = alertController;
[alertController addAction:[UIAlertAction actionWithTitle:buttonTitle
style:buttonStyle
handler:^(__unused UIAlertAction *action) {
switch (type) {
case RCTAlertViewStylePlainTextInput:
case RCTAlertViewStyleSecureTextInput:
callback(@[buttonKey, [alertController.textFields.firstObject text]]);
callback(@[buttonKey, [weakAlertController.textFields.firstObject text]]);
break;
case RCTAlertViewStyleLoginAndPasswordInput: {
NSDictionary<NSString *, NSString *> *loginCredentials = @{
@"login": [alertController.textFields.firstObject text],
@"password": [alertController.textFields.lastObject text]
@"login": [weakAlertController.textFields.firstObject text],
@"password": [weakAlertController.textFields.lastObject text]
};
callback(@[buttonKey, loginCredentials]);
break;
@ -172,7 +171,7 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
}
if (!_alertControllers) {
_alertControllers = [NSMutableArray new];
_alertControllers = [NSHashTable weakObjectsHashTable];
}
[_alertControllers addObject:alertController];