views:

196

answers:

3

I have created a subclass for a UIButton and was hoping to pass a custom property to it. However, it's not working and I've since read that subclassing a UIButton isn't a great idea.

MY question is how do I assign a custom property to a button? I am creating a button which is being placed in the headerview of a grouped table. I want to pass to that button the section number. I've done this successfully with a UISwitch in each row, but can't use the same method for the UIButton.

So I create a button

MattsButtonClass *button = [MattsButtonClass buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(240, 15, 45, 30);
button.MFsectionNo = section; //this would be 1, 2 etc
//etc

So how do I actually do this? you'll see that my UIbutton has a subclass, which looks like this

//.h file
@interface MattsButtonClass : UIButton {
    int MFsectionNo;
}

@property (nonatomic) int MFsectionNo;

@end

//.m file
@implementation MattsButtonClass

@synthesize MFsectionNo;


@end

The error on the above is

-[UIRoundedRectButton MFsectionNo:]: unrecognized selector sent to instance 0x5673650
2010-09-07 22:41:39.751 demo4[67445:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIRoundedRectButton MFsectionNo:]: unrecognized selector sent to instance 0x5673650'

Is what I am trying not possible? Thanks for any help...

+3  A: 

You could probably just use the tag property of UIButton to store your section number (maybe with an offset, since tag is 0 by default)

Thomas Müller
+1. Simple yet effective if a plain integer is sufficient.
Eiko
Yes that would work - NO idea why I didn't think of that. Will let you know how it goes!
Matt Facer
worked perfectly. SO simple. Thanks to others for options too.
Matt Facer
+2  A: 

This is not possible because you are using the function call:

[MattsButtonClass buttonWithType:UIButtonTypeCustom]

That message will return a UIButton not a MattsButtonClass. That is why the property does not exist on the returned object. This makes it difficult to subclass UIButton. However you may be able to achieve your desired function by the following:

MattsButtonClass *button = [[MattsButtonClass alloc] initWithFrame:CGRectMake(240, 15, 45, 30)];
button.MFsectionNo = section;
rickharrison
A: 

Maybe keep an array that has references to the buttons in each section header?

-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIButton *myButton = [[UIButton alloc] init];
    [myButton addTarget:self action:@selector(myButton_touchUpInside:) forControlEvents:UIControlEventTouchUpInside];

    // previously defined as an instance variable of your viewcontroller
    // NSMutableArray *sectionHeaderButtons;
    [sectionHeaderButtons insertObject:myButton atIndex:section];
}

Then in the handler for the TouchUpInside event of the button:

- (void)myButton_touchUpInside:(id)sender
{
    int i;
    for (i = 0; i < [sectionHeaderButtons count]; i++)
    {
        if ([sectionHeaderButtons objectAtIndex:i] == sender)
            break; // now you know what section index was touched
    }
}

If the section index of the touched button is what you're after, this should do the trick. However, it's not optimal if:

  1. You're rearranging the TableView sections, or
  2. You've got A LOT of sections

Hope this helps.

jtrim