Обнаружение, которое UIButton было нажато в UITableView

У меня есть UITableView с 5 UITableViewCells . Каждая ячейка содержит UIButton которая настроена следующим образом:

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

Мой вопрос заключается в следующем: в buttonPressedAction: как узнать, какая кнопка была нажата. Я рассмотрел использование тегов, но я не уверен, что это лучший маршрут. Я бы хотел как-то пометить indexPath на элементе управления.

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

Каков стандартный способ сделать это?

Редактировать:

Я как-то решил это, выполнив следующее. Я все же хотел бы получить мнение, является ли это стандартным способом его выполнения или есть лучший способ?

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

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

В примере с аксессуарами Apple используется следующий метод:

 [button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 

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

 - (void)checkButtonTapped:(id)sender { CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; if (indexPath != nil) { ... } } 

Я нашел метод использования супервизора супервизора для получения ссылки на indexPath ячейки отлично. Благодаря iphonedevbook.com (macnsmith) для текста ссылки чата

 -(void)buttonPressed:(id)sender { UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview]; NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell]; ... } 

Вот как я это делаю. Простой и лаконичный:

 - (IBAction)buttonTappedAction:(id)sender { CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; ... 

Нашел хорошее решение этой проблемы в другом месте, не путаясь с тегами на кнопке:

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

Как насчет отправки информации, такой как NSIndexPath в UIButton используя инъекцию времени выполнения.

1) Требуется время выполнения при импорте

2) добавить статическую константу

3) добавьте NSIndexPath к вашей кнопке во время выполнения, используя:

(void) setMetaData: (id) target withObject: (id) newObj

4) при нажатии кнопки получить метаданные, используя:

(ID) Metadata: (ID) целевой

наслаждаться

  #import  static char const * const kMetaDic = "kMetaDic"; #pragma mark - Getters / Setters - (id)metaData:(id)target { return objc_getAssociatedObject(target, kMetaDic); } - (void)setMetaData:(id)target withObject:(id)newObj { objc_setAssociatedObject(target, kMetaDic, newObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #On the cell constructor - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { .... cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; .... [btnSocial addTarget:self action:@selector(openComments:) forControlEvents:UIControlEventTouchUpInside]; #add the indexpath here or another object [self setMetaData:btnSocial withObject:indexPath]; .... } #The action after button been press: - (IBAction)openComments:(UIButton*)sender{ NSIndexPath *indexPath = [self metaData:sender]; NSLog(@"indexPath: %d", indexPath.row); //Reuse your indexpath Now } 
 func buttonAction(sender:UIButton!) { var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tablevw) let indexPath = self.tablevw.indexPathForRowAtPoint(position) let cell: TableViewCell = tablevw.cellForRowAtIndexPath(indexPath!) as TableViewCell println(indexPath?.row) println("Button tapped") } 

Чтобы сделать ответ (@Vladimir), это Swift:

 var buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView) var indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)! 

Хотя проверка indexPath != nil дает мне палец … «NSIndexPath не является подтипом NSString»

Я бы использовал свойство тега, как вы сказали, установив тег следующим образом:

 [button setTag:indexPath.row]; 

затем, получив тег внутри кнопки ButtonPressedAction, вот так:

 ((UIButton *)sender).tag 

Или

 UIButton *button = (UIButton *)sender; button.tag; 

Хотя мне нравится тег … Если вы не хотите использовать tags по какой-либо причине, вы можете создать член NSArray из NSArray кнопок:

 NSArray* buttons ; 

затем создайте эти кнопки перед рендерингом tableView и вставьте их в массив.

Затем внутри функции tableView:cellForRowAtIndexPath: вы можете сделать:

 UIButton* button = [buttons objectAtIndex:[indexPath row] ] ; [cell.contentView addSubview:button]; 

Затем в функции buttonPressedAction: вы можете сделать

 - (void)buttonPressedAction:(id)sender { UIButton* button = (UIButton*)sender ; int row = [buttons indexOfObject:button] ; // Do magic } 

ОБРАТИТЬ СЕКЦИИ – я сохранил NSIndexPath в пользовательском UITableViewCell

IN CLKIndexPricesHEADERTableViewCell.xib

IN IB Добавить UIButton в XIB – DONT добавить действие!

Добавить выход @property (сохранить, неатомный) IBOutlet UIButton * buttonIndexSectionClose;

НЕ CTRL + DRAG действие в IB (сделано в коде ниже)

 @interface CLKIndexPricesHEADERTableViewCell : UITableViewCell ... @property (retain, nonatomic) IBOutlet UIButton *buttonIndexSectionClose; @property (nonatomic, retain) NSIndexPath * indexPathForCell; @end 

В viewForHeaderInSection (также должен работать для cellForRow …. и т. Д., Если в таблице есть только 1 раздел)

 - viewForHeaderInSection is called for each section 1...2...3 - get the cell CLKIndexPricesHEADERTableViewCell - getTableRowHEADER just does the normal dequeueReusableCellWithIdentifier - STORE the indexPath IN the UITableView cell - indexPath.section = (NSInteger)section - indexPath.row = 0 always (we are only interested in sections) - (UIView *) tableView:(UITableView *)tableView1 viewForHeaderInSection:(NSInteger)section { //Standard method for getting a UITableViewCell CLKIndexPricesHEADERTableViewCell * cellHEADER = [self getTableRowHEADER]; 

… используйте раздел, чтобы получить данные для вашей ячейки

…заполните это

  indexName = ffaIndex.routeCode; indexPrice = ffaIndex.indexValue; // [cellHEADER.buttonIndexSectionClose addTarget:self action:@selector(buttonDELETEINDEXPressedAction:forEvent:) forControlEvents:UIControlEventTouchUpInside]; cellHEADER.indexPathForCell = [NSIndexPath indexPathForRow:0 inSection:section]; return cellHEADER; } 

USER нажимает кнопку DELETE на заголовке раздела, и этот вызов

 - (void)buttonDELETEINDEXPressedAction:(id)sender forEvent:(UIEvent *)event { NSLog(@"%s", __PRETTY_FUNCTION__); UIView * parent1 = [sender superview]; // UiTableViewCellContentView //UIView *myContentView = (UIView *)parent1; UIView * parent2 = [parent1 superview]; // custom cell containing the content view //UIView * parent3 = [parent2 superview]; // UITableView containing the cell //UIView * parent4 = [parent3 superview]; // UIView containing the table if([parent2 isMemberOfClass:[CLKIndexPricesHEADERTableViewCell class]]){ CLKIndexPricesHEADERTableViewCell *myTableCell = (CLKIndexPricesHEADERTableViewCell *)parent2; //UITableView *myTable = (UITableView *)parent3; //UIView *mainView = (UIView *)parent4; NSLog(@"%s indexPath.section,row[%d,%d]", __PRETTY_FUNCTION__, myTableCell.indexPathForCell.section,myTableCell.indexPathForCell.row); NSString *key = [self.sortedKeysArray objectAtIndex:myTableCell.indexPathForCell.section]; if(key){ NSLog(@"%s DELETE object at key:%@", __PRETTY_FUNCTION__,key); self.keyForSectionIndexToDelete = key; self.sectionIndexToDelete = myTableCell.indexPathForCell.section; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Remove Index" message:@"Are you sure" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil]; alertView.tag = kALERTVIEW_REMOVE_ONE_INDEX; [alertView show]; [alertView release]; //------ }else{ NSLog(@"ERROR: [%s] key is nil for section:%d", __PRETTY_FUNCTION__,myTableCell.indexPathForCell.section); } }else{ NSLog(@"ERROR: [%s] CLKIndexPricesHEADERTableViewCell not found", __PRETTY_FUNCTION__); } } 

В этом примере я добавил кнопку «Удалить», поэтому должен показать UIAlertView, чтобы подтвердить это

Я храню раздел и ключ в словаре, хранящем информацию о разделе в ivar в VC

 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if(alertView.tag == kALERTVIEW_REMOVE_ONE_INDEX){ if(buttonIndex==0){ //NO NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex); //do nothing } else if(buttonIndex==1){ //YES NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex); if(self.keyForSectionIndexToDelete != nil){ //Remove the section by key [self.indexPricesDictionary removeObjectForKey:self.keyForSectionIndexToDelete]; //sort the keys so sections appear alphabetically/numbericsearch (minus the one we just removed) [self updateTheSortedKeysArray]; //Delete the section from the table using animation [self.tableView beginUpdates]; [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:self.sectionIndexToDelete] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView endUpdates]; //required to trigger refresh of myTableCell.indexPathForCell else old values in UITableViewCells [self.tableView reloadData]; }else{ NSLog(@"ERROR: [%s] OBJECT is nil", __PRETTY_FUNCTION__); } } else { NSLog(@"ERROR: [%s] UNHANDLED BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex); } }else { NSLog(@"ERROR: [%s] unhandled ALERTVIEW TAG:%d", __PRETTY_FUNCTION__,alertView.tag); } } 
 A better way would be to subclass your button and add a indexPath property to it. //Implement a subclass for UIButton. @interface NewButton:UIButton @property(nonatomic, strong) NSIndexPath *indexPath; Make your button of type NewButton in the XIB or in the code whereever you are initializing them. Then in the cellForRowAtIndexPath put the following line of code. button.indexPath = indexPath; return cell; //As usual Now in your IBAction -(IBAction)buttonClicked:(id)sender{ NewButton *button = (NewButton *)sender; //Now access the indexPath by buttons property.. NSIndexPath *indexPath = button.indexPath; //:) } 

Это работает и для меня, спасибо @Cocoanut

Я нашел метод использования супервизора супервизора для получения ссылки на indexPath ячейки отлично. Благодаря iphonedevbook.com (macnsmith) для текста ссылки чата

 -(void)buttonPressed:(id)sender { UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview]; NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell]; ... } 

вы можете использовать шаблон тега:

 - (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:[indexPath row]]; //use the row as the current tag [cell.contentView addSubview:button]; [button release]; } UIButton *button = (UIButton *)[cell viewWithTag:[indexPath row]]; //use [indexPath row] [button setTitle:@"Edit" forState:UIControlStateNormal]; return cell; } - (void)buttonPressedAction:(id)sender { UIButton *button = (UIButton *)sender; //button.tag has the row number (you can convert it to indexPath) } 

Я что-то упускаю? Не можете ли вы использовать отправителя для идентификации кнопки. Отправитель даст вам такую ​​информацию:

 > 

Затем, если вы хотите изменить свойства кнопки, скажите фоновое изображение, которое вы просто скажете отправителю:

 [sender setBackgroundImage:[UIImage imageNamed:@"new-image.png"] forState:UIControlStateNormal]; 

Если вам нужен тег, то метод ACBurk в порядке.

 // how do I know which button sent this message? // processing button press for this row requires an indexPath. 

Довольно просто:

 - (void)buttonPressedAction:(id)sender { UIButton *button = (UIButton *)sender; CGPoint rowButtonCenterInTableView = [[rowButton superview] convertPoint:rowButton.center toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rowButtonCenterInTableView]; MyTableViewItem *rowItem = [self.itemsArray objectAtIndex:indexPath.row]; // Now you're good to go.. do what the intention of the button is, but with // the context of the "row item" that the button belongs to [self performFooWithItem:rowItem]; } 

Хорошо работает для меня: P

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

создать nsmutable массив и поместить всю кнопку в этот массив usint [array addObject: yourButton];

в методе нажатия кнопки

  (void)buttonPressedAction:(id)sender { UIButton *button = (UIButton *)sender; for(int i=0;i<[yourArray count];i++){ if([buton isEqual:[yourArray objectAtIndex:i]]){ //here write wat u need to do } } 

Небольшая вариация ответа Cocoanuts (что помогло мне это решить), когда кнопка была в нижнем колонтитуле стола (что мешает вам найти «щелкнув по ячейке»:

 -(IBAction) buttonAction:(id)sender; { id parent1 = [sender superview]; // UiTableViewCellContentView id parent2 = [parent1 superview]; // custom cell containing the content view id parent3 = [parent2 superview]; // UITableView containing the cell id parent4 = [parent3 superview]; // UIView containing the table UIView *myContentView = (UIView *)parent1; UITableViewCell *myTableCell = (UITableViewCell *)parent2; UITableView *myTable = (UITableView *)parent3; UIView *mainView = (UIView *)parent4; CGRect footerViewRect = myTableCell.frame; CGRect rect3 = [myTable convertRect:footerViewRect toView:mainView]; [cc doSomethingOnScreenAtY:rect3.origin.y]; } 

Я всегда использую tags.

Вам нужно подclassифицировать UITableviewCell и обрабатывать нажатие кнопки оттуда.

Это просто; сделать пользовательскую ячейку и вынуть кнопку

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = @"identifier"; customCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; cell.yourButton.tag = indexPath.Row; - (void)buttonPressedAction:(id)sender 

изменить идентификатор в указанном выше методе (UIButton *)

Вы можете получить значение, на которое нажата кнопка, используя sender.tag.

Подclass кнопки для сохранения требуемого значения, возможно, создаст протокол (ControlWithData или что-то еще). Установите значение при добавлении кнопки в ячейку таблицы. В вашем событии касания проверьте, подчиняется ли отправитель протоколу и извлекает данные. Обычно я сохраняю ссылку на фактический объект, который отображается в ячейке представления таблицы.

ОБНОВЛЕНИЕ SWIFT 2

Вот как узнать, какая кнопка была нажата + отправить данные в другой ViewController из этой кнопки indexPath.row поскольку я предполагаю, что это точка для большинства!

 @IBAction func yourButton(sender: AnyObject) { var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView) let indexPath = self.tableView.indexPathForRowAtPoint(position) let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as UITableViewCell print(indexPath?.row) print("Tap tap tap tap") } 

Для тех, кто использует class ViewController и добавил tableView, я использую ViewController вместо TableViewController, поэтому я вручную добавил tableView для доступа к нему.

Вот код для передачи данных другому VC при нажатии этой кнопки и передаче indexPath.row

 @IBAction func moreInfo(sender: AnyObject) { let yourOtherVC = self.storyboard!.instantiateViewControllerWithIdentifier("yourOtherVC") as! YourOtherVCVIewController var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView) let indexPath = self.tableView.indexPathForRowAtPoint(position) let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as UITableViewCell print(indexPath?.row) print("Button tapped") yourOtherVC.yourVarName = [self.otherVCVariable[indexPath!.row]] self.presentViewController(yourNewVC, animated: true, completion: nil) } 

Обратите внимание, что я использую пользовательскую ячейку, этот код отлично работает для меня

  @IBAction func call(sender: UIButton) { var contentView = sender.superview; var cell = contentView?.superview as EmployeeListCustomCell if (!(cell.isKindOfClass(EmployeeListCustomCell))) { cell = (contentView?.superview)?.superview as EmployeeListCustomCell } let phone = cell.lblDescriptionText.text! //let phone = detailObject!.mobile! let url:NSURL = NSURL(string:"tel://"+phone)!; UIApplication.sharedApplication().openURL(url); } 

Решение Криса Швердта, но потом в Свифте, помогло мне:

 @IBAction func rateButtonTapped(sender: UIButton) { let buttonPosition : CGPoint = sender.convertPoint(CGPointZero, toView: self.ratingTableView) let indexPath : NSIndexPath = self.ratingTableView.indexPathForRowAtPoint(buttonPosition)! print(sender.tag) print(indexPath.row) } 

Эта проблема состоит из двух частей:

1) Получение указательного пути UITableViewCell который содержит нажатый UIButton

Есть несколько предложений, таких как:

  • Обновление tag cellForRowAtIndexPath: в cellForRowAtIndexPath: метод с использованием значения row указателя пути. Это нехорошее решение, так как оно требует обновления tag непрерывно и не работает с представлениями таблиц с несколькими разделами.

  • Добавление свойства NSIndexPath в пользовательскую ячейку и его обновление вместо tag cellForRowAtIndexPath: методе cellForRowAtIndexPath: Это решает проблему с несколькими разделами, но все еще не очень хорошо, так как требует обновления.

  • Сохранение слабой привязки родительского UITableView в пользовательской ячейке при ее создании и использование метода indexPathForCell: для получения указательного пути. Кажется немного лучше, нет необходимости обновлять что-либо в cellForRowAtIndexPath: но при этом требуется установка слабой ссылки при создании пользовательской ячейки.

  • Использование свойства superView ячейки для получения ссылки на родительский UITableView . Не нужно добавлять какие-либо свойства в пользовательскую ячейку, и нет необходимости устанавливать / обновлять что-либо при создании / позже. Но superView зависит от деталей реализации iOS. Поэтому его нельзя использовать напрямую.

Но это может быть достигнуто с помощью простого цикла, так как мы уверены, что соответствующая ячейка должна находиться в UITableView:

 UIView* view = self; while (view && ![view isKindOfClass:UITableView.class]) view = view.superview; UITableView* parentTableView = (UITableView*)view; 

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

 - (NSIndexPath *)indexPath { UIView* view = self; while (view && ![view isKindOfClass:UITableView.class]) view = view.superview; return [(UITableView*)view indexPathForCell:self]; } 

С этого UIButton этот метод можно использовать для определения того, какой UIButton нажат.

2) Информирование других участников о событии нажатия кнопки

После того, как внутренне зная, какой UIButton нажат, в какой пользовательской ячейке с точным указательным путем эта информация должна быть отправлена ​​другим сторонам (скорее всего, диспетчер представлений обрабатывает UITableView ). Таким образом, это событие нажатия кнопки может обрабатываться с аналогичным абстрактом и логическим уровнем до метода didSelectRowAtIndexPath: для делегата UITableView.

Для этого можно использовать два подхода:

a) Делегирование: пользовательская ячейка может иметь свойство delegate и может определять протокол. Когда кнопка нажата, она просто выполняет свои методы delegate свойстве delegate . Но это свойство delegate необходимо установить для каждой пользовательской ячейки при их создании. В качестве альтернативы, пользовательская ячейка может также использовать свои методы делегирования в своем делете родительского табличного представления.

b) Центр уведомлений: пользовательские ячейки могут определять имя пользовательского уведомления и размещать это уведомление с информацией об указателе и родительской таблице, представленной в объекте userInfo . Не нужно ничего устанавливать для каждой ячейки, достаточно добавить наблюдателя для уведомления пользовательской ячейки.

Я использую решение подclassа UIButton и я думал, что должен просто поделиться им здесь, коды в Swift:

 class ButtonWithIndexPath : UIButton { var indexPath:IndexPath? } 

Тогда не забудьте обновить его indexPath в cellForRow(at:)

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let returnCell = tableView.dequeueReusableCell(withIdentifier: "cellWithButton", for: indexPath) as! cellWithButton ... returnCell.button.indexPath = IndexPath returnCell.button.addTarget(self, action:#selector(cellButtonPressed(_:)), for: .touchUpInside) return returnCell } 

Поэтому, когда вы отвечаете на событие кнопки, вы можете использовать его как

 func cellButtonPressed(_ sender:UIButton) { if sender is ButtonWithIndexPath { let button = sender as! ButtonWithIndexPath print(button.indexPath) } } 

С Swift 4.2 и iOS 12 UITableView имеет метод indexPathForRow(at:) . indexPathForRow(at:) имеет следующее объявление:

 func indexPathForRow(at point: CGPoint) -> IndexPath? 

Возвращает индексный путь, определяющий строку и раздел в данной точке.


Следующий полный код показывает, как реализовать indexPathForRow(at:) , чтобы получить соответствующий IndexPath из UIButton находящегося в UITableViewCell :

 import UIKit class CustomCell: UITableViewCell { let button = UIButton(type: .system) override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) button.setTitle("Tap", for: .normal) contentView.addSubview(button) button.translatesAutoresizingMaskIntoConstraints = false button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true button.topAnchor.constraintEqualToSystemSpacingBelow(contentView.topAnchor, multiplier: 1).isActive = true button.leadingAnchor.constraintGreaterThanOrEqualToSystemSpacingAfter(contentView.leadingAnchor, multiplier: 1).isActive = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 
 import UIKit class TableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() tableView.register(CustomCell.self, forCellReuseIdentifier: "Cell") } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 3 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell cell.button.addTarget(self, action: #selector(printIndexPath), for: .touchUpInside) return cell } @objc func printIndexPath(_ sender: UIButton) { let point = sender.convert(CGPoint.zero, to: tableView) guard let indexPath = tableView.indexPathForRow(at: point) else { return } print(indexPath) } } 
  • : непризнанный селектор, отправленный в экземпляр
  • UITableView dequeueReusableCellWithIdentifier Theory
  • Определите, видна ли ячейка таблицы.
  • Настройка стиля UITableViewCell при использовании iOS 6 UITableView dequeueReusableCellWithIdentifier: forIndexPath:
  • Как отобразить несколько столбцов в UITableView?
  • Прокрутка UITableView внутри UIScrollView
  • UITableview с более чем одной пользовательской ячейкой с Swift
  • UITableView прокручивается с определенной скоростью?
  • Выберите несколько строк в UITableview
  • Вид сетки в iPhone SDK
  • Калибровка UITableViewCell для включения и выключения при использовании
  • Давайте будем гением компьютера.