Iphone – Getting “EXC_BAD_ACCESS” when accessing instance variable from within UITableView delegate method

delegatesexc-bad-accessiphoneuitableview

My iPhone application blows up when it accesses an instance variable from within one of the UITableView delegate methods. I think I'm retaining it so I do not understand why I can't access it without a problem.

Here's my .h file

#import <Foundation/Foundation.h>
#import "AlertSummaryCell.h"
#import "AlertDetailViewController.h"

@interface AlertSummaryTableViewController : UITableViewController {
NSDictionary *alerts;
NSString *alertKind;
}

@property (nonatomic, retain) NSDictionary *alerts;
@property (nonatomic, retain) NSString *alertKind;

@end

In my .m, the application dies at the first NSLog call:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@"AlertSummaryTableViewController.numberOfRowsInSection entered");
NSLog(@"  alerts description = %@", [alerts description]);
// To know how many alert summaries we have, get the value for count out of the input dictionary
int theCount = [[alerts objectForKey:@"count"] intValue];
NSLog(@"  Going to return %d",theCount);
return theCount;
}

What am I missing???

There's no problem at all in the viewDidLoad method:

 - (void)viewDidLoad {
 NSLog(@"AlertSummaryTableViewController.viewDidLoad entered");
 NSLog(@"  alerts description = %@", [alerts description]);

 // We want the View title to include the alert count
 // To know how many alert summaries we have, get the value for count out of the input dictionary
 int theCount = [[alerts objectForKey:@"count"] intValue];

 // Now construct the title text and set our views title to it
 NSString *myTitle = [[NSString alloc] initWithFormat:@"%@ Alerts (%d)",alertKind,theCount];
 [self setTitle: myTitle];

 // Memory cleanup
 [myTitle release];

 [super viewDidLoad];
 }

Best Answer

For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BEST way to track these down is use NSZombieEnabled.

This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.

It especially helps in background threads when the Debugger sometimes craps out on any useful information.

VERY IMPORTANT TO NOTE however, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever release, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
Related Topic