views:

608

answers:

3

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];
 }
+3  A: 

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!");
coneybeare
Thank you for the tip!!!!!
Dale
A: 

I assume you've checked to make alerts is set. If you try to call [alerts objectForKey:] on a nil reference you'd get that error.

pzearfoss
A: 

The problem turned out to be the way I was setting alerts. Rather than using the setter method, which would have retained the object, I ignorantly just did this:

alerts = [[UIDictionary alloc] init];     // or something like this

Which compiled without any warnings or errors, as it should I guess.

By using the setter,

[self setAlerts:[[UIDictionary alloc] init];   // again I'm going from memory so ...

which I had to create, alerts was "retained" as it needed to be and all was well once the view controller loaded.

I'm very new to Objective-C and having to mess with memory management but I'm finally starting to see the light after about 4 weeks of working with it and the iPhone SDK.

Dale