I’v encountered EXC_BAD_ACCESS error in my app. Or to be more specific in one of my classes. It is Custom UIAlertView class. I couldn’t catch when it throws EXC_BAD_ACCESS in usage. Sometimes it works great just as expected, and in all suden it craches… Here is whole class
@implementation AlertPassword
int counter = 3;
@synthesize done;
@synthesize alertText;
@synthesize msg;
- (void) showAlert :(NSString*) title
{
if(counter != 3){
if(counter == 1)
{
NSString *msgs = @"Last warning";
msg = msgs;
}
else
{
NSString *msgs = [NSString stringWithFormat:@"WRONG PIN. %d times remaining",counter];
msg = msgs;
}
}
else
{
NSString *msgs = @"Enter your pin";
msg = msgs;
}
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Security" message:msg delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: nil];
_alert = alert;
_alert.alertViewStyle = UIAlertViewStyleSecureTextInput;
alertText = [_alert textFieldAtIndex:0];
alertText.keyboardType = UIKeyboardTypeNumberPad;
alertText.placeholder = @"Pin";
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controlTextDidChange:)
name:UITextFieldTextDidChangeNotification object:alertText];
[_alert show];
[_alert release];
[[NSNotificationCenter defaultCenter] removeObserver:UITextFieldTextDidChangeNotification];
}
- (void)controlTextDidChange:(NSNotification *)notification {
{
NSString *pin = [[NSUserDefaults standardUserDefaults] stringForKey:@"Pin"];
if ([notification object] == alertText)
{
if (alertText.text.length == pin.length)
{
if(counter != 0)
{
if([alertText.text isEqualToString:pin])
{
[_alert dismissWithClickedButtonIndex:0 animated:NO];
[self.tableViewController openSettings];
counter = 3;
}
else
{
counter--;
[_alert dismissWithClickedButtonIndex:0 animated:NO];
[self showAlert:@""];
}
}
else
{
[_alert dismissWithClickedButtonIndex:0 animated:NO];
[[NSUserDefaults standardUserDefaults] setObject:NULL
forKey:@"Telephone"];
[[NSUserDefaults standardUserDefaults] setObject:NULL
forKey:@"Pin"];
[[NSUserDefaults standardUserDefaults] synchronize];
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"" message:AMLocalizedString(@"EraseData", nil) delegate:nil cancelButtonTitle:AMLocalizedString(@"Ok", nil) otherButtonTitles:nil];
counter = 3;
[av show];
[av release];
}
}
}
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *pincheck = [[NSUserDefaults standardUserDefaults] stringForKey:@"pinCheck"];
if (buttonIndex == 0)
{
if(pincheck.intValue == 1)
{
NSLog(@"app kill");
exit(0);
}
else
{
NSLog(@"dismiss");
}
}
}
@end
Here is where i initialize and use this class.
case 5:
NSLog(@"Add remove");
if (pincheck != NULL && pin != NULL){
if([pincheck isEqualToString:@"0"])
{
AlertPassword *alert = [AlertPassword alloc];
alert.tableViewController = self;
NSString *msg = @"Enter your pin code to access:";
[alert showAlert:msg];
// [alert release];
}
break;
}
else
{
NSLog(@"Is null");
[Menu load2View:self];
}
break;
I though maybe it was because i do not release alert. But adding [alert release]; Made to have EXC_BAD_ACCESS directly after the user tries to enter something. Without [alert release]; it works. But sometimes it craches with EXC_BAD_ACCESS
Also sometimes it gets
2012-11-08 12:11:27.451 kodinisRaktas[2485:19d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSMallocBlock__ dismissWithClickedButtonIndex:animated:]: unrecognized selector sent to instance 0x947aae0'
But I also have no idea why this happends
Please help, I’m pretty new to objective-c and ios, and I have no idea how to get rid of this, I guess someone with a bit of experience will see whats wrong in my code.
I’v just saw, that EXC_BAD_ACCESS or unrecognized selector throws if you push cancel for 4-5 times or more, and then try to type something.
EXC_BAD_ACCESS is mostly due to bad memory handling. The alert has most likely become an zombie… I would have the alert as a property with strong/retain. You should hold on to it while displaying. Not release after “show”.
When you set up the first you can do like this
Note calling “show” will also retain it, but that does not change the fact that you need to too.
Wait for the delegate callback and release it.
Tip: It may be easier to handle if you use UIAlertView combined with blocks. http://gkoreman.com/blog/2011/02/15/uialertview-with-blocks/