VansFannel
VansFannel

Reputation: 45961

Custom UITableViewCell with UIButton: which button has been clicked?

I'm developing an iOS 4 application with latest SDK and XCode 4.2.

I have a UITableView with sections and with custom UITableViewCell. Every cell has a UIButton and all of these buttons has the same target for UIControlEventTouchUpInside.

This is my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* cellIdentifier = @"CalendarCell";

    CalendarEventCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil)
    {
        NSArray* topLevelObjects =  [[NSBundle mainBundle] loadNibNamed:@"CalendarEventCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if ([currentObject isKindOfClass:[CalendarEventCell class]])
            {
                cell = (CalendarEventCell *)currentObject;
                [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal) forControlEvents:UIControlEventTouchUpInside];
                break;
            }
        }
    }
...
}

When user touch inside that button, how can I know on which section and row was the cell that has been clicked?

Upvotes: 3

Views: 10712

Answers (4)

Adnan Ahmad
Adnan Ahmad

Reputation: 447

Assign Tag value to button like that in cellForRowAtIndexPath method

  1. cell.addToCalendarButton.tag=indexPath.row
  2. When you add method to button also send the sender so assign method to button like that.

    [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal:)forControlEvents:UIControlEventTouchUpInside];

  3. In your method read the relevant row like that

    -(IBAction)addEventToiCal:(id)sender { NSLog("current row is %d",[sender tag]); }

If you want to now about the section then indexPath do such thing then

- (void)addEventToiCal:(id)sender event:(id)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];

   NsLog("value of indePath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);

}

Assign your method at cellforRowAtIndexPath Like that.

[cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal:event:)forControlEvents:UIControlEventTouchUpInside];

Upvotes: 2

Mustafa
Mustafa

Reputation: 20564

BNRXIBCell is an excellent solution, for iOS 5 and above. It's a UITableViewCell subclass, intended to be subclassed, to forward action messages from cell subviews to a controller.

Upvotes: 0

David M. Syzdek
David M. Syzdek

Reputation: 15788

Place a tag on the button. For example:

CalendarEventCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil)
{
    NSArray* topLevelObjects =  [[NSBundle mainBundle] loadNibNamed:@"CalendarEventCell" owner:nil options:nil];

    for(id currentObject in topLevelObjects)
    {
        if ([currentObject isKindOfClass:[CalendarEventCell class]])
        {
            cell = (CalendarEventCell *)currentObject;
            [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal) forControlEvents:UIControlEventTouchUpInside];
            break;
        }
    }
}
cell.addToCalendarButton.tag = ((indexPath.section & 0xFFFF) << 16) |
                               (indexPath.row & 0xFFFF);

You will need to change your selector to @selector(addEventToiCal:) and update the method to -(void) addEventToiCal:(UIButton *)sender.

You can then add something like the following to -addEventToiCal:

if (!([sender isKindOfClass:[UIButton class]]))
    return;
NSUInteger section = ((sender.tag >> 16) & 0xFFFF);
NSUInteger row     = (sender.tag & 0xFFFF);
NSLog(@"Button in section %i on row %i was pressed.", section, row);

Upvotes: 6

macbirdie
macbirdie

Reputation: 16193

Set button's target to a method in the cell instead of setting the target to the controller itself, create a delegate protocol for the cell with a method like tappedButton:(UIButton *)button inCell:(UITableViewCell *)cell and set the controller as cell's delegate. In the target method call that delegate method.

Then in controller's delegate method implementation you can find out cell's NSIndexPath by calling UITableView's tableView:indexPathForCell:.

Upvotes: 3

Related Questions