tags:

views:

346

answers:

2

I built a UIButton subclass that is a very basic checkbox. Everything is working (e.g. I'm getting the events I expect, the drawRect method is called when I expect, etc), but my image isn't drawing. I've checked that my image is not nil and that my images are different.

Code:

-(void)awakeFromNib {
    [super awakeFromNib];
    [self addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
    self.state=YES;
}

-(void) buttonClick {
    self.state = !self.state;
    [self setNeedsDisplay];
}

-(void)drawRect:(CGRect)rect {
    UIImage *img = nil;
    if (self.state) {
        img = [self backgroundImageForState:UIControlStateSelected];
    }
    else {
        img = [self backgroundImageForState:UIControlStateNormal];
    }
    [img drawInRect:rect];
}

Checking the value of 'img' before it is drawn:

Printing description of img:
<UIImage: 0x52a710>
(gdb) continue

Printing description of img:
<UIImage: 0x52a5d0>

The background images are being set in the NIB. If I change the selected state in IB, I see the proper image show up. I'm also getting a valid image back from the call (which I don't if I try to get imageForState, which is not set in the NIB).

The reason for the subclass is that I need a checkbox. UIButton doesn't do that and UISwitch is hideously ugly for all but the most utilitarian views.

Thoughts?

Thanks.

tj

Edit: Added all the code for the subclass

+2  A: 

Where are you setting backgroundImageForState? Are you sure it's the correct image? iPhone OS might be giving you a transparent (blank) image as a default.

Second, I wouldn't use the passed-in "rect" param to draw the image. That's just telling you the area it wants you to redraw, not necessarily anything else. Instead use

CGRectMake(0, 0, img.size.width, img.size.height)

or something similar.

Finally, why are you doing custom drawing? I've done something very similar, and you absolutely don't need to subclass and implement drawRect. UIButton has an extremely rich set of options built in for images, including "highlighted" and "selected" images that will draw automatically with user interaction. Let us know what you need to accomplish.

Adam Ernst
I added details to the question above about your first set of questions. What I get in the simulator is the default image I set in the NIB. I think it is coming from when the Checkbox is serialized to the NIB, not from my code.I've changed the code to use my own rect (which is the same as I was getting passed), and it didn't affect it.I've also added all the code so you can see why the custom drawing. UIButton doesn't do what I need it to do.
Travis Jensen
I am open to better ways of doing this, BTW, if it is just something I'm not familiar with. I essentially need to be able to keep the "selected state" even when the user isn't actively tapping the button.
Travis Jensen
A: 

Just because the UIImage isn't nil doesn't mean it contains image data.

Check the case of your file name.
I've done this several times:

@"CheckBox.png" and @"checkbox.png" are 2 different names to the iPhone.

It seems you may be doing a little premature optimizing as well.

I wouldn't dive into drawRect: for my first option.

Use a UIButton subclass (you only need to subclass to track state). Set the button up in IB and position it where you want it. Connect the button to the method below and simply swap the images on the click:

- (IBAction)toggle:(id)sender{

    MyButtonSubClass *aButton = (MyButtonSubClass*)sender;

    [aButton toggleChecked];

    if(aButton.checked)
        [aButton setImage:checkedImage forState:UIControlStateNormal];
    else
        [aButton setImage:uncheckedImage forState:UIControlStateNormal];


}

optionally you can not subclass UIButton and track state in the controller

Corey Floyd