Botão Get clique dentro UITableViewCell

Eu tenho um controlador de exibição com uma exibição de tabela e uma ponta separada para o modelo de célula de tabela. O modelo de célula tem alguns botões. Eu quero acessar o botão clique junto com o índice da célula clicada dentro do controlador de exibição onde eu defini a exibição de tabela.

Então eu tenho ViewController.h e ViewController.m onde eu tenho o UITableView e TableTemplate.h , TableTemplate.m e TableTemplate.xib onde eu tenho a ponta definida. Eu quero o evento de clique de botão com índice de célula em ViewController.m .

Qualquer ajuda sobre como posso fazer isso?

1) Em seu método cellForRowAtIndexPath: atribua tag de botão como índice:

 cell.yourbutton.tag = indexPath.row; 

2) Adicione o alvo e a ação para seu botão como abaixo:

 [cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; 

3) Codifique as ações com base no índice, conforme abaixo em ViewControler :

 -(void)yourButtonClicked:(UIButton*)sender { if (sender.tag == 0) { // Your code here } } 

Atualizações para várias seções:

Você pode verificar este link para detectar o clique do botão na exibição de tabela para várias linhas e seções.

Delegados são o caminho a percorrer.

Como visto com outras respostas usando visualizações, pode ficar desatualizado. Quem sabe amanhã pode haver outro invólucro e talvez precise usar cell superview]superview]superview]superview] . E se você usar tags, você acabaria com um número de condições if else para identificar a célula. Para evitar todos os delegates configurados. (Ao fazer isso, você estará criando uma class de célula utilizável. Você pode usar a mesma class de célula como uma class base e tudo o que você precisa fazer é implementar os methods de delegação.)

Primeiro precisamos de uma interface (protocolo) que será usada pela célula para comunicar (delegar) cliques de botão. ( Você pode criar um arquivo .h separado para o protocolo e incluí-lo no controlador de exibição de tabela e nas classs de células personalizadas OU apenas adicioná-lo na class de célula personalizada que, de qualquer maneira, será incluída no controlador de exibição de tabela )

 @protocol CellDelegate  - (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data; @end 

Inclua este protocolo na célula personalizada e no controlador de visualização de tabela. E certifique-se de que o controlador de exibição de tabela confirme este protocolo.

Na célula personalizada, crie duas propriedades:

 @property (weak, nonatomic) iddelegate; @property (assign, nonatomic) NSInteger cellIndex; 

Em UIButton IBAction delegate click: (O mesmo pode ser feito para qualquer ação na class de célula personalizada que precise ser delegada de volta para ver o controlador )

 - (IBAction)buttonClicked:(UIButton *)sender { if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) { [self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"]; } } 

No controlador de exibição de tabela cellForRowAtIndexPath depois de dequeing a célula, defina as propriedades acima.

 cell.delegate = self; cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table. 

E implemente o delegado no controlador de exibição de tabela:

 - (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data { // Do additional actions as required. NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data); } 

Essa seria a abordagem ideal para obter ações de botão de célula personalizada no controlador de exibição de tabela.

Em vez de brincar com tags, tomei uma abordagem diferente. Tornou delegado para minha subclass de UITableViewCell (OptionButtonsCell) e incluiu uma var indexPath. Do meu botão no storyboard eu conectei o @IBAction ao OptionButtonsCell e lá eu envio o método delegate com o indexPath certo para qualquer pessoa interessada. Na célula para o caminho do índice, eu configurei o indexPath atual e ele funciona 🙂

Deixe o código falar por si:

Swift 3 Xcode 8

OptionButtonsTableViewCell.swift

 import UIKit protocol OptionButtonsDelegate{ func closeFriendsTapped(at index:IndexPath) } class OptionButtonsTableViewCell: UITableViewCell { var delegate:OptionButtonsDelegate! @IBOutlet weak var closeFriendsBtn: UIButton! var indexPath:IndexPath! @IBAction func closeFriendsAction(_ sender: UIButton) { self.delegate?.closeFriendsTapped(at: indexPath) } } 

MyTableViewController.swift

 class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {... func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell cell.delegate = self cell.indexPath = indexPath return cell } func closeFriendsTapped(at index: IndexPath) { print("button tapped at index:\(index)") } 

Isso deve ajudar: –

 UITableViewCell* cell = (UITableViewCell*)[sender superview]; NSIndexPath* indexPath = [myTableView indexPathForCell:cell]; 

Aqui o remetente é a instância do UIButton que está enviando o evento. myTableView é a instância do UITableView com a qual você está lidando.

Basta obter a referência de célula correta e todo o trabalho está concluído.

Pode ser necessário remover os botões do contentView da célula e adicioná-los diretamente à instância do UITableViewCell como sua subvisualização.

Ou

Você pode formular um esquema de nomenclatura de tags para diferentes UIButtons em cell.contentView. Usando essa tag, mais tarde você pode saber as informações de linha e seção conforme necessário.

O código a seguir pode ajudar você.

Eu tomei UITableView com class de célula de protótipo personalizada chamada UITableViewCell dentro de UIViewController .

Então eu tenho ViewController.h , ViewController.m e TableViewCell.h , TableViewCell.m

Aqui está o código para isso:

ViewController.h

 @interface ViewController : UIViewController @property (strong, nonatomic) IBOutlet UITableView *tblView; @end 

ViewController.m

 @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return (YourNumberOfRows); } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifier = @"cell"; __weak TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; if (indexPath.row==0) { [cell setDidTapButtonBlock:^(id sender) { // Your code here }]; } return cell; } 

Classe de célula personalizada:

 TableViewCell.h @interface TableViewCell : UITableViewCell @property (copy, nonatomic) void (^didTapButtonBlock)(id sender); @property (strong, nonatomic) IBOutlet UILabel *lblTitle; @property (strong, nonatomic) IBOutlet UIButton *btnAction; - (void)setDidTapButtonBlock:(void (^)(id sender))didTapButtonBlock; @end 

e

 UITableViewCell.m @implementation TableViewCell - (void)awakeFromNib { // Initialization code [self.btnAction addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside]; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } - (void)didTapButton:(id)sender { if (self.didTapButtonBlock) { self.didTapButtonBlock(sender); } } 

Nota : Aqui eu peguei todas as UIControls usando o Storyboard.

Espero que isso possa ajudá-lo…!!!

A razão que eu gosto abaixo técnica porque também me ajuda a identificar a seção da tabela.

Adicionar botão na célula cellForRowAtIndexPath:

  UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)]; [selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun [selectTaskBtn addTarget:self action:@selector(addTask:) forControlEvents:UIControlEventTouchDown]; [cell addsubview: selectTaskBtn]; 

AddTask do evento:

 -(void)addTask:(UIButton*)btn { CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; if (indexPath != nil) { int currentIndex = indexPath.row; int tableSection = indexPath.section; } } 

Espera essa ajuda.

Swift 2.2

Você precisa adicionar o alvo para esse botão.

 myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside) 

FunctionName: connected // por exemplo

E, claro, você precisa definir a tag desse botão desde que você está usando.

 myButton.tag = indexPath.row 

Você pode conseguir isso subclassificando o UITableViewCell. Use-o no construtor de interface, solte um botão nessa célula, conecte-o via saída e lá vai você.

Para obter a tag na function conectada:

 func connected(sender: UIButton) { let buttonTag = sender.tag // Do any additional setup } 

O código de Tarun não funciona no iOS7, já que a estrutura do UITableViewCell mudou e agora ele teria “UITableViewCellScrollView”.

Este post Obtendo UITableViewCell com superview no iOS 7 tem uma boa solução criando um loop para encontrar a visão pai correta, independentemente de quaisquer alterações futuras na estrutura. Tudo se resume a criar um loop:

  UIView *superView = [sender superview]; UIView *foundSuperView = nil; while (nil != superView && nil == foundSuperView) { if ([superView isKindOfClass:[UITableViewCell class]]) { foundSuperView = superView; } else { superView = superView.superview; } } 

O link tem código para uma solução mais reutilizável, mas isso deve funcionar.

Eu acho mais simples subclass o botão dentro do seu celular (Swift 3):

 class MyCellInfoButton: UIButton { var indexPath: IndexPath? } 

Na sua class de celular:

 class MyCell: UICollectionViewCell { @IBOutlet weak var infoButton: MyCellInfoButton! ... } 

Na fonte de dados da exibição da tabela ou da visualização de coleção, ao remover o cache da célula, forneça ao botão seu caminho de índice:

 cell.infoButton.indexPath = indexPath 

Então você pode simplesmente colocar esses códigos no seu controlador de visão de tabela:

 @IBAction func handleTapOnCellInfoButton(_ sender: MyCellInfoButton) { print(sender.indexPath!) // Do whatever you want with the index path! } 

E não se esqueça de definir a class do botão no seu Interface Builder e vinculá-lo à function handleTapOnCellInfoButton !


editado:

Usando injeção de dependência. Para configurar a chamada de fechamento:

 class MyCell: UICollectionViewCell { var someFunction: (() -> Void)? ... @IBAction func didTapInfoButton() { someFunction?() } } 

e injete o encerramento no método willDisplay do delegado da vista de coleção:

  func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { (cell as? MyCell)?.someFunction = { print(indexPath) // Do something with the indexPath. } } 

Swift 3 com um fechamento

Uma boa solução é usar um encerramento em um UITableViewCell personalizado para chamar o viewController para uma ação.

Na célula:

 final class YourCustomCell: UITableViewCell { var callbackClosure: (() -> Void)? // Configure the cell here func configure(object: Object, callbackClosure: (() -> Void)?) { self.callbackClosure = callbackClosure } // MARK: - IBAction extension YourCustomCell { @IBAction fileprivate func actionPressed(_ sender: Any) { guard let closure = callbackClosure else { return } closure() } } 

No modo de exibição Controlador: Delegado de Tableview

 extension YourViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { guard let cell: YourCustomCell = cell as? YourCustomCell else { return } cell.configure(object: object, callbackClosure: { [weak self] in self?.buttonAction() }) } } fileprivate extension YourViewController { func buttonAction() { // do your actions here } } 

Seu trabalho para mim.

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UIButton *Btn_Play = (UIButton *)[cell viewWithTag:101]; [Btn_Play addTarget:self action:@selector(ButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; } -(void)ButtonClicked:(UIButton*)sender { CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.Tbl_Name]; NSIndexPath *indexPath = [self.Tbl_Name indexPathForRowAtPoint:buttonPosition]; } 
 // Add action in cell for row at index path -tableView cell.buttonName.addTarget(self, action: #selector(ViewController.btnAction(_:)), for: .touchUpInside) // Button Action @objc func btnAction(_ sender: AnyObject) { var position: CGPoint = sender.convert(.zero, to: self.tableView) let indexPath = self.tableView.indexPathForRow(at: position) let cell: UITableViewCell = tableView.cellForRow(at: indexPath!)! as UITableViewCell } 

A resposta do @Mani é boa, no entanto, as tags de visualizações dentro do contentView da célula geralmente são usadas para outras finalidades. Você pode usar a tag da célula em vez disso (ou a tag contentView da célula):

1) Em seu método cellForRowAtIndexPath: atribua a tag da célula como índice:

 cell.tag = indexPath.row; // or cell.contentView.tag... 

2) Adicione o alvo e a ação para seu botão como abaixo:

 [cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; 

3) Criar método que retorne linha do remetente (obrigado @Stenio Ferreira):

 - (NSInteger)rowOfSender:(id)sender { UIView *superView = sender.superview; while (superView) { if ([superView isKindOfClass:[UITableViewCell class]]) break; else superView = superView.superview; } return superView.tag; } 

4) Codifique as ações com base no índice:

 -(void)yourButtonClicked:(UIButton*)sender { NSInteger index = [self rowOfSender:sender]; // Your code here } 

CustomTableCell.h é um UITableViewCell:

 @property (weak, nonatomic) IBOutlet UIButton *action1Button; @property (weak, nonatomic) IBOutlet UIButton *action2Button; 

MyVC.m após as importações:

 @interface MYTapGestureRecognizer : UITapGestureRecognizer @property (nonatomic) NSInteger dataint; @end 

Dentro de “cellForRowAtIndexPath” em MyVC.m:

 //CustomTableCell CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; //Set title buttons [cell.action1Button setTitle:[NSString stringWithString:NSLocalizedString(@"action1", nil)] forState:UIControlStateNormal]; [cell.action2Button setTitle:[NSString stringWithString:NSLocalizedString(@"action2", nil)] forState:UIControlStateNormal]; //Set visibility buttons [cell.action1Button setHidden:FALSE]; [cell.action2Button setHidden:FALSE]; //Do 1 action [cell.action1Button addTarget:self action:@selector(do1Action :) forControlEvents:UIControlEventTouchUpInside]; //Do 2 action MYTapGestureRecognizer *action2Tap = [[MYTapGestureRecognizer alloc] initWithTarget:self action:@selector(do2Action :)]; cancelTap.numberOfTapsRequired = 1; cancelTap.dataint = indexPath.row; [cell.action2Button setUserInteractionEnabled:YES]; [cell.action2Button addGestureRecognizer:action2Tap]; 

MyVC.m:

 -(void)do1Action :(id)sender{ //do some action that is not necessary fr data } -(void)do2Action :(UITapGestureRecognizer *)tapRecognizer{ MYTapGestureRecognizer *tap = (MYTapGestureRecognizer *)tapRecognizer; numberTag = tap.dataint; FriendRequest *fr = [_list objectAtIndex:numberTag]; //connect with a WS o do some action with fr data //actualize list in tableView [self.myTableView reloadData]; } 
 cell.show.tag=indexPath.row; [cell.show addTarget:self action:@selector(showdata:) forControlEvents:UIControlEventTouchUpInside]; -(IBAction)showdata:(id)sender { UIButton *button = (UIButton *)sender; UIStoryboard *storyBoard; storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; SecondViewController *detailView = [storyBoard instantiateViewControllerWithIdentifier:@"SecondViewController"]; detailView.string=[NSString stringWithFormat:@"%@",[_array objectAtIndex:button.tag]]; [self presentViewController:detailView animated:YES completion:nil]; }