tags:

views:

183

answers:

1

In my drawing routine for a custom UITableViewCell, was using the following without any problems:

CGContextRef context = UIGraphicsGetCurrentContext();   
UIColor* backgroundColor = [UIColor colorForHex:@"FFFEFF"];
[backgroundColor set];
CGContextFillRect(context, rect);

Of course, this is quite standard except for my interface on the UIColor object for colorForHex which takes a string and breaks this down into RGB values of 0-255 and returns a UIColor object with the following (a is defaulted to 1.0f):

return [UIColor colorWithRed:((float) r/255.0f) green:((float) g/255.0f) blue:((float) b/255.0f) alpha:a];

Now this works fine, but I tried to improve this and centralise the the colour (and font) creation to try to speed up the draw routine as much as possible. This is where I get the problem.

I create a protocol using:

@protocol ItemListTableViewCellDelegate
-(UIFont*) fontForId:(int) fontID;
-(UIColor*) colorForId:(int) colorID;
@end

The controller implements this protocol and implements the colorForId method as:

-(UIColor*) colorForId:(int) colorID {
    UIColor* requestedColor = nil;
    switch (colorID) {
     case BACKGROUND_COLOR_ID:
     {
      requestedColor = backgroundColor;
     }
      break;
    }
    return requestedColor;
}

where backgroundColor is created as a member of the controller as a UIColor* in the initWithStyle method of the controller. This is being called and the backgroundColor is being created.

The cell has an NSObject<ItemListTableViewCellDelegate>* cellDelegate member which is initialised with the controller so that the cell can call

UIColor* backgroundColor = [cellDelegate colorForId:BACKGROUND_COLOR_ID];

which appears to return the correct pointer to the UIColor in the controller, but when 'set' is called on this colour in the cell draw method then the cell throws a BAD ACCESS error and I can't work out why.

Any pointers in the right direction?

+2  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