Detectar qué UIButton se presionó en un UITableView
Tengo un UITableView
con 5 UITableViewCells
. Cada celda contiene un UIButton
que está configurado de la siguiente manera:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:1];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell viewWithTag:1];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
Mi pregunta es la siguiente: en el buttonPressedAction:
método, ¿cómo sé qué botón se ha presionado? He considerado usar etiquetas, pero no estoy seguro de que sea la mejor ruta. Me gustaría poder etiquetar de alguna manera indexPath
el control.
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
// how do I know which button sent this message?
// processing button press for this row requires an indexPath.
}
¿Cuál es la forma estándar de hacer esto?
Editar:
Lo he resuelto haciendo lo siguiente. Todavía me gustaría tener una opinión sobre si esta es la forma estándar de hacerlo o si existe una forma mejor.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
[button setTag:indexPath.row];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
int row = button.tag;
}
Lo que es importante tener en cuenta es que no puedo configurar la etiqueta en la creación de la celda ya que es posible que la celda se retire de la cola. Se siente muy sucio. Debe haber una mejor manera.
En el ejemplo de accesorios de Apple se utiliza el siguiente método:
[button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
Luego, en el controlador táctil, se recupera la coordenada táctil y la ruta del índice se calcula a partir de esa coordenada:
- (void)checkButtonTapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
...
}
}
Descubrí que el método de usar la supervista de la supervista para obtener una referencia al indexPath de la celda funcionó perfectamente. Gracias a iphonedevbook.com (macnsmith) por el texto del enlace de sugerencia.
-(void)buttonPressed:(id)sender {
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...
}
Así es como lo hago. Sencillo y conciso:
- (IBAction)buttonTappedAction:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero
toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
...
}