Permalink
Browse files

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 #10407

Differential Revision: D4078649

Pulled By: lacker

fbshipit-source-id: 8509e7e7142379a81d5b28c9067c085bad8bb5cb
  • Loading branch information...
1 parent d932c96 commit 49667db1c8ec7b430e57eee1e4b8f38f50c5ed6d littlesome committed with Facebook Github Bot Oct 26, 2016
Showing with 6 additions and 7 deletions.
  1. +6 −7 React/Modules/RCTAlertManager.m
@@ -31,9 +31,7 @@ @interface RCTAlertManager()
@implementation RCTAlertManager
{
- NSMutableArray<UIAlertController *> *_alertControllers;
- NSMutableArray<RCTResponseSenderBlock> *_alertCallbacks;
- NSMutableArray<NSArray<NSString *> *> *_alertButtonKeys;
+ NSHashTable *_alertControllers;
}
RCT_EXPORT_MODULE()
@@ -148,18 +146,19 @@ - (void)invalidate
} 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 @@ - (void)invalidate
}
if (!_alertControllers) {
- _alertControllers = [NSMutableArray new];
+ _alertControllers = [NSHashTable weakObjectsHashTable];
}
[_alertControllers addObject:alertController];

0 comments on commit 49667db

Please sign in to comment.