Rory Byrne
Rory Byrne

Reputation: 923

Can I have a UIButton's action method take a second parameter?

I want to place a button in each cell of a table. I want the target to be a class that I'm using to handle all of the API calls. I want the button's method to be in the friendController class, not in the UITableView's View Controller.

[cell.deleteButton addTarget:friendController 
action:@selector(deleteFriend: forID:cell.idNumber) 
forControlEvents:UIControlEventTouchUpInside];

Where friendController is the class with the API calls, and cell.idNumber is an instance variable of each cell containing the ID number of the user associated with that cell.

I know (well, I presume) that I could set the cell itself as the target and then have a method which looks like:

-(IBAction)deleteFriend:(id)sender {
    [friendController deleteFriend:self.idNumber];
}

Is that correct? It doesn't seem like an elegant way of doing this. Is there a way to do it the way I want to, or is there a better way to do it?

EDIT: I emboldened the last crucial part of my question. I want the button's action to be a method in another class (friendController). friendController is a class I created to house all of the API calls and business logic. If I set the target to friendController, must the action be a method in that class?

Upvotes: 1

Views: 1397

Answers (4)

dichen
dichen

Reputation: 1633

Since the button is inside a UITableViewCell, you might consider subclass a UITableViewCell with your property idNumber(I don't like reuse Tag because it can only be an integer) and a delegate:

    @protocol MyTableViewCellDelegate;

@interface MyTableViewCell : UITableViewCell

@property (nonatomic, assign) NSInteger idNumber;

@property (nonatomic, weak) id<MyTableViewCellDelegate> delegate;

@end

@protocol MyTableViewCellDelegate <NSObject>

-(void) shouldDeleteFriendById:(NSInteger)idNumber;

@end

And handle the button action inside the MyTableViewCell implementation:

- (void) myInit
{
    UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    [button addTarget:self action:@selector(onButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

    [self addSubview:button];
}

- (IBAction)onButtonClicked:(id)sender
{
    [self.delegate shouldDeleteFriendById:self.idNumber];
}

Then implement cell's delegate in your tableViewController:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *cell = (MyTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];

    // Configure the cell...
    cell.idNumber = indexPath.row;
    cell.delegate = self;

    return cell;
}

- (void) shouldDeleteFriendById:(NSInteger)idNumber
{
    NSLog(@"should delete by id:%d", idNumber);
}

Upvotes: 0

sooper
sooper

Reputation: 6039

You can do this two ways.

Subclassing UIButton

The first would be to subclass UIButton and create a property for the idNumber. So you would first set the property like so:

cell.deleteButton.idNumber = /* set id here */
[cell.deleteButton addTarget:friendController 
action:@selector(deleteFriend:) 
forControlEvents:UIControlEventTouchUpInside];

and then access it inside your deleteFriend: method:

- (IBAction)deleteFriend:(id)sender {
    YourButtonClass *button = (YourButtonClass *)sender;
    [friendController deleteFriend:button.idNumber];
}

Retrieve the idNumber directly from the cell

Described in this post you can grab the index path of the button's cell and then access the idNumber from there.

Upvotes: 3

Erhan
Erhan

Reputation: 906

With 2 parameters indicating the control that sends the message and the event that triggered the message:

action:@selector(buttonAction:Second:)

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btn addTarget:self action:@selector(buttonAction:Second:) forControlEvents:UIControlEventTouchUpInside];
}

- (void)buttonAction:(NSString *)firstCharacter
              Second:(NSNumber *)second
{

}

Upvotes: 0

nprd
nprd

Reputation: 1942

Use the tag property of the button.

cell.deleteButton.tag = cell.idNumber;
[cell.deleteButton addTarget:friendController action:@selector(deleteFriend:) forControlEvents:UIControlEventTouchUpInside];

In the method, you can use the tag to retrieve the cell idNumber

-(IBAction)deleteFriend:(id)sender {
     int idNumber = ((UIButton *) sender).tag;
     [friendController deleteFriend: idNumber];
} 

Upvotes: 0

Related Questions