Обнаружение того, какой 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.
}


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



Edit:



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



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


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

560   26  

26 ответов:

в 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)
    {
     ...
    }
}

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

-(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)метаданные: (id)цель

наслаждайтесь

    #import <objc/runtime.h>
    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")
    }

to do (@Vladimir)'s ответ быстрый:

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

хотя проверка indexPath != nil дает мне палец..."NSIndexPath не является подтипом NSString"

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

[button setTag:indexPath.row];

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

((UIButton *)sender).tag

или

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

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

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

в CLKIndexPricesHEADERTableViewCell.xib

В IB добавьте UIButton в XIB-не добавляйте действие!

Add outlet @property (retain, nonatomic) IBOutlet UIButton *buttonIndexSectionClose;

не CTRL + перетащите действие В 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;
}

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

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

Я нашел метод использования супервизора superview для получения ссылки на 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)
}

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

<UIButton: 0x4b95c10; frame = (246 26; 30 30); opaque = NO; tag = 104; layer = <CALayer: 0x4b95be0>>

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

[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 и поместите кнопку all в этот массив 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];
}

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

вам нужно подкласс 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 *)

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

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

SWIFT 2 UPDATE

вот как узнать, какая кнопка была нажата + отправить данные в другой 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")

    }

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

здесь код для передачи данных в другой ВК при нажатии на эту кнопку и передаче клетки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);
    }

решение Криса Швердта, но тогда в Swift работал для меня:

@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

есть некоторые предложения, такие как:

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

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

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

  • С помощью ячейки superView свойство для получения ссылки на parent 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 нажата.

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

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

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

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

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

я использую решение, которое подкласс 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)
    }

}

Comments

    Ничего не найдено.