Получить нажатие кнопки внутри UITableViewCell

У меня есть controller представления с табличным представлением и отдельный нить для шаблона ячейки таблицы. Шаблон ячейки имеет несколько кнопок. Я хочу получить доступ к щелчку кнопки вместе с индексом ячейки, нажатой внутри controllerа вида, где я определил представление таблицы.

Поэтому у меня есть ViewController.h и ViewController.m где у меня есть UITableView и TableTemplate.h , TableTemplate.m и TableTemplate.xib где я определил TableTemplate.xib . Я хочу событие нажатия кнопки с индексом ячейки в ViewController.m .

Любая помощь в том, как я могу это сделать?

1) В вашем cellForRowAtIndexPath: назначьте тег кнопки как индекс:

 cell.yourbutton.tag = indexPath.row; 

2) Добавьте цель и действие для своей кнопки, как показано ниже:

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

3) Кодовые действия, основанные на индексе, как ViewControler ниже в ViewControler :

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

Обновления для нескольких разделов:

Вы можете проверить эту ссылку, чтобы обнаружить кнопку щелчка в виде таблицы для нескольких строк и разделов.

Делегаты – это путь.

Как видно из других ответов, использующих представления, может устареть. Кто знает, что завтра может быть другая shell, и, возможно, потребуется использовать cell superview]superview]superview]superview] . И если вы используете tags, вы в конечном итоге получите n число условий if else, чтобы идентифицировать ячейку. Чтобы избежать всех заданных делегатов. (При этом вы создадите повторно используемый class ячеек. Вы можете использовать тот же class ячеек, что и базовый class, и все, что вам нужно сделать, это реализовать методы делегата.)

Сначала нам нужен интерфейс (протокол), который будет использоваться клеточным сообщением (делегировать) нажатием кнопки. ( Вы можете создать отдельный файл .h для протокола и включить как в controller табличного представления, так и в пользовательские classы ячеек или просто добавить его в пользовательский class ячеек, который в любом случае будет включен в controller табличного представления )

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

Включите этот протокол в пользовательский controller ячеек и таблиц. И убедитесь, что controller табличного представления подтверждает этот протокол.

В пользовательской ячейке создайте два свойства:

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

В деле UIButton IBAction нажмите: ( То же самое можно сделать для любого действия в пользовательском classе ячейки, который необходимо делегировать обратно, чтобы просмотреть controller )

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

В controllerе таблицы cellForRowAtIndexPath после деинкретизации ячейки задайте указанные выше свойства.

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

И реализовать делегата в controllerе табличного представления:

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

Это был бы идеальный подход для получения пользовательских действий кнопок ячеек в controllerе табличного представления.

Вместо того, чтобы играть с тегами, я использовал другой подход. Сделал делегат для моего подclassа UITableViewCell (OptionButtonsCell) и добавил indexPath var. Из моей кнопки в раскадровке я подключил @IBAction к OptionButtonsCell, и там я посылаю метод делегирования с нужным indexPath всем, кого это интересует. В ячейке для указательного пути я устанавливаю текущий indexPath, и он работает 🙂

Пусть код говорит сам за себя:

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)") } 

Это должно помочь: –

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

Здесь отправитель – это экземпляр UIButton, который отправляет событие. myTableView – это экземпляр UITableView, с которым вы имеете дело.

Просто верните ссылку на ячейку, и вся работа будет выполнена.

Возможно, вам придется удалить кнопки из содержимого содержимого контента и добавить их непосредственно в экземпляр UITableViewCell, поскольку он является подвью.

Или

Вы можете сформулировать схему именования тегов для разных UIButtons в cell.contentView. Используя этот тег, позже вы сможете узнать информацию о строке и разделе по мере необходимости.

Следующий код может помочь вам.

Я взял UITableView с пользовательским classом прототипа classа UITableViewCell внутри UIViewController .

Поэтому у меня есть ViewController.h , ViewController.m и TableViewCell.h , TableViewCell.m

Вот код для этого:

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; } 

Пользовательский class ячейки:

 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 

а также

 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); } } 

Примечание . Здесь я взял все UIControls используя Storyboard.

Надеюсь, что может помочь вам … !!!

Причина, по которой мне нравится ниже, потому что она также помогает мне определить раздел таблицы.

Добавить кнопку в ячейке 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:

 -(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; } } 

Надеется на эту помощь.

Swift 2.2

Вам нужно добавить цель для этой кнопки.

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

FunctionName: connected // например

И, конечно, вам нужно установить тег этой кнопки, так как вы ее используете.

 myButton.tag = indexPath.row 

Вы можете добиться этого путем подclassа UITableViewCell. Используйте его в построителе интерфейса, отпустите кнопку на этой ячейке, подключите ее через розетку и там вы идете.

Чтобы получить тег в подключенной функции:

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

Код Tarun не работает на iOS7, поскольку структура UITableViewCell изменилась, и теперь он получит вместо этого «UITableViewCellScrollView».

Этот пост Получение UITableViewCell с супервизором в iOS 7 имеет хорошее решение, создающее цикл для поиска правильного родительского представления независимо от любых будущих изменений в структуре. Это сводится к созданию цикла:

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

Ссылка имеет код для более многоразового решения, но это должно работать.

Я считаю, что проще всего подclassировать кнопку внутри вашей ячейки (Swift 3):

 class MyCellInfoButton: UIButton { var indexPath: IndexPath? } 

В вашем classе ячейки:

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

В источнике данных представления таблицы или коллекции, когда вычеркиваете ячейку, задайте кнопке свой индексный путь:

 cell.infoButton.indexPath = indexPath 

Таким образом, вы можете просто поместить этот код в свой controller табличного представления:

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

И не забудьте установить class кнопки в вашем handleTapOnCellInfoButton интерфейса и связать его с функцией handleTapOnCellInfoButton !


отредактирован:

Использование инъекции зависимостей. Чтобы настроить вызов закрытия:

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

и ввести закрытие в методе willDisplay делегата представления коллекции:

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

Swift 3 с закрытием

Хорошим решением является закрытие в пользовательском UITableViewCell для обратного вызова viewController для действия.

В ячейке:

 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() } } 

В диспетчере представлений: делегат 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 } } 

Его работа для меня.

  - (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 } 

Ответ @Mani хорош, однако tags представлений внутри содержимого contentView часто используются для других целей. Вместо этого вы можете использовать тег ячейки (или тег contentView ячейки):

1) В вашем cellForRowAtIndexPath: назначьте тег ячейки как индекс:

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

2) Добавьте цель и действие для своей кнопки, как показано ниже:

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

3) Создайте метод, который возвращает строку отправителя (спасибо @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) Кодовые действия, основанные на индексе:

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

CustomTableCell.h – это UITableViewCell:

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

MyVC.m после импорта:

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

Внутри «cellForRowAtIndexPath» в 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]; } 
  • Как работает новый механизм автоматического подсчета ссылок?
  • Почему вы используете символ подчеркивания для переменной экземпляра, но не соответствующее ему свойство?
  • Преобразование миллисекунд в NSDate
  • Синглтон в iOS 5?
  • drawRect не вызывается в моем подclassе UIImageView
  • NSOperation на iPhone
  • Использовать метод didSelectRowAtIndexPath или prepareForSegue для UITableView?
  • В чем разница между использованием CGFloat и float?
  • Apple Mach-O и множественные ошибки «неопределенных символов» с использованием OpenCV
  • Почему мой коллега MCSession отключается случайно?
  • Сохранение UIColor и загрузка из NSUserDefaults
  • Давайте будем гением компьютера.