Pregunta

I have 2 view controllers, ViewController 1(VC1) and 2(VC2). In VC2 I have a back and done button. On clicking back button it goes directly to VC1 and on done it makes an api call and when it gets a response it shows an alert view and clicking ok goes back to VC1. Now when I make a api call a loading bar shows up and disappears when I get response and shows the AlertView. But if during that fraction of second when the loading disappears and AlertView is going to be popped up if I click on back and the view changes to VC1, the alert appears on VC1 and results in a crash.

This is a rare case as no user will purposely try for it but I was wondering if that crash can be managed without disabling the back button. I think there can be other instance such cases like if we are making an asynchronous calls and if the user is allowed to use UI while waiting for response and if any error alert that was suppose to show on one ViewController shows up in another may result in crash since the delegate that alert is referring to is that of the previous view controller. So is there any way to handle this kind of crash efficiently?

//Alert View sample
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[[message objectAtIndex:1] capitalizedString] message:[message objectAtIndex:0] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] ;
[alert setTag:701];
[alert show];

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if ([alertView tag] == 701)
        if (buttonIndex == 0)
        {
            [self.navigationController popViewControllerAnimated:YES];
        }


}
¿Fue útil?

Solución

The proper way to fix this problem is to use an instance variable to keep a reference to the alert view.

This instance variable should be set to nil in the alertView:didDismissWithButtonIndex: delegate method.

In the view controller's dealloc method, you call dismissWithClickedButtonIndex:animated: if the instance variable is still set.

Assume _alertView is the instance variable.

Create the alert:

_alertView = [[UIAlertView alloc] initWithTitle:[[message objectAtIndex:1] capitalizedString] message:[message objectAtIndex:0] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] ;
[_alertView setTag:701];
[_alertView show];

Update your existing alertView:clickedButtonAtIndex: method:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if ([alertView tag] == 701) {
         _alertView.delegate = nil;            
         _alertView = nil;
        if (buttonIndex == 0) {
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
}

Add:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    _alertView = nil;
}

Add:

- (void)dealloc {
    if (_alertView) {
        _alertView.delegate = nil;
        [_alertView dismissWithClickedButtonIndex:_alertView.cancelButtonIndex animated:NO];
        _alertView = nil;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top