6

I currently have a button defined in a cell and a method to track its UITouchDown action as shown:

- (void) clickedCallSign:(id)sender {

    int index = [sender tag];
    NSLog(@"event triggered %@",index);

}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    //Callsign button
    UIButton *button;

    CGRect rect = CGRectMake(TEXT_OFFSET_X, BORDER_WIDTH, LABEL_WIDTH, LABEL_HEIGHT);
    button = [[UIButton alloc] initWithFrame:rect];
    cell.tag=[indexPath row];
    button.tag=[indexPath row];
    [button addTarget:self action:@selector(clickedCallSign:) forControlEvents:UIControlEventTouchDown];
    [button setBackgroundColor:[UIColor redColor]];
    [button setTitle:@"hello" forState:UIControlStateNormal];
    [cell.contentView addSubview:button];
    [button release];   
}

However when I click a cell in the simulator, the console debug message is: "event triggered (null)" and my app crashes shortly after.

How can I correctly get the indexPath.row value into my clickedCallSign method?

Keavon
  • 6,837
  • 9
  • 51
  • 79
dpigera
  • 3,339
  • 5
  • 39
  • 60

3 Answers3

2

Tag is good until you haven't both sections and rows. Try another way to get index path:

- (void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath {

    //...

    [button addTarget:self action:@selector(clickedCallSign:withEvent:) forControlEvents:UIControlEventTouchDown];

    //...

}

// Get the index path of the cell, where the button was pressed
- (NSIndexPath*)indexPathForEvent:(id)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    return [self.tableView indexPathForRowAtPoint:currentTouchPosition];
}

- (IBAction)clickedCallSign:(id)sender withEvent:(UIEvent*)event
{
    NSIndexPath* buttonIndexPath = [self indexPathForEvent:event];
}
JastinBall
  • 873
  • 8
  • 25
2

If you don't want to use the tag field, have the button invoke this method:

- (void)tapAccessoryButton:(UIButton *)sender
{
    UIView *parentView = sender.superview;

    // the loop should take care of any changes in the view heirarchy, whether from
    // changes we make or apple makes.
    while (![parentView.class isSubclassOfClass:UITableViewCell.class])
        parentView = parentView.superview;

    if ([parentView.class isSubclassOfClass:UITableViewCell.class]) {
        UITableViewCell *cell = (UITableViewCell *) parentView;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        [self tableView:self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
    }
}
mahboudz
  • 39,196
  • 16
  • 97
  • 124
2

First off, index is an int, so your NSLog needs to look like this (note the %d):

NSLog(@"event triggered %d", index);

(It's possible that this leads to a crash, but it's also likely that something else entirely is going that causes the instability.)

Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
  • the '%d' did the trick of getting the indexPath.row value into the clickedCallSign :) the app still crashes though.. with this stack trace: -[UIButton setText:]: unrecognized selector sent to instance 0x6877a10 2010-08-13 21:48:30.324 RF[8047:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setText:]: unrecognized selector sent to instance 0x6877a10' – dpigera Aug 14 '10 at 04:51
  • You're probably over-releasing something somewhere. The memory management in the code snippet you show looks fine, so something elsewhere is wrong. – Ben Zotto Aug 14 '10 at 05:22
  • 1
    actually.. found the solution i needed right here: http://developer.apple.com/iphone/library/samplecode/Accessory/Introduction/Intro.html Thanks for the help though. I really appreciate it. – dpigera Aug 14 '10 at 06:12