Как я могу отслеживать путь индекса кнопки в ячейке табличного представления? - PullRequest
22 голосов
/ 19 мая 2010

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

Ответы [ 8 ]

31 голосов
/ 08 января 2013

Если вам неудобно полагаться на button.superview, этот метод должен быть немного более надежным, чем некоторые другие ответы здесь:

UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];
25 голосов
/ 19 мая 2010

Это перестало работать с iOS 7 ; проверить ответ Майка Веллера вместо

- (IBAction)clickedButton:(id)sender {
    UIButton *button = (UIButton *)sender;
    UITableViewCell *cell = (UITableViewCell *)button.superview;
    UITableView *tableView = (UITableView *)cell.superview;
    NSIndexPath *indexPath = [tableView indexPathForCell:cell];
}

или короче:

- (IBAction)clickedButton:(id)sender {
    NSIndexPath *indexPath = [(UITableView *)sender.superview.superview indexPathForCell:(UITableViewCell *)sender.superview];
}

Оба непроверены!

21 голосов
/ 10 апреля 2013

Просмотр иерархий представлений с помощью .superview (как демонстрируют все существующие ответы) - действительно плохой способ сделать что-то. Если структура UITableViewCell изменится (что уже было раньше), ваше приложение сломается. Если в вашем коде указано .superview.superview, то должны прозвучать сигналы тревоги.

Кнопка и ее обработчик должны быть добавлены в пользовательский подкласс UITableViewCell и размещены там. Вот где оно принадлежит.

Подкласс ячейки может затем делегировать событие кнопки через стандартный интерфейс делегирования или блок. Вы должны стремиться к чему-то вроде этого:

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = ...;

    // ...

    cell.onButtonTapped = ^{
        [self buttonSelectedAtIndexPath:indexPath];
    }

    // OR

    cell.delegate = self;

    // ...
}

(Примечание: если вы идете по блочному маршруту, вам нужно будет использовать __weak самоссылку для предотвращения сохранения циклов, но я подумал, что это загромождает пример).

Если вы выберете маршрут делегата, вам потребуется следующий метод делегата:

- (void)cellButtonPressed:(UITableViewCell *)cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    // ...
}

Ваш код теперь имеет полный доступ к соответствующему контексту при обработке события.

Реализация этого интерфейса на вашем классе ячеек должна быть простой.

9 голосов
/ 18 июля 2012

Я не знаю, почему мне нужно дважды вызвать метод superview, чтобы получить UITableViewCell.

Обновление:

Спасибо за Qiulang, теперь я получил это.

«Это потому, что в SDK теперь добавлен закрытый класс UITableViewCellContentView для UITableViewCell, который теперь является супервизором кнопки». - Qiulang

UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
6 голосов
/ 25 сентября 2013

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

-(NSIndexPath*)GetIndexPathFromSender:(id)sender{

    if(!sender) { return nil; }

    if([sender isKindOfClass:[UITableViewCell class]])
    {
        UITableViewCell *cell = sender;
        return [self.tableView indexPathForCell:cell];
    }

    return [self GetIndexPathFromSender:((UIView*)[sender superview])];
}


-(void)ButtonClicked:(id)sender{
    NSIndexPath *indexPath = [self GetIndexPathFromSender:sender];
}
4 голосов
/ 11 марта 2015

Я создал один метод для получения indexPath, надеюсь, это поможет вам.

Создать действие кнопки (aMethod :) в cellForRowAtIndexPath

-(void) aMethod:(UIButton *)sender
{
    // Calling Magic Method which will return us indexPath.
    NSIndexPath *indexPath = [self getButtonIndexPath:sender];

    NSLog(@"IndexPath: %li", indexPath.row);
    NSLog(@"IndexRow: %li", indexPath.section);
}

// Вот магический метод для получения indexPath кнопки

-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
    CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
    return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
3 голосов
/ 21 ноября 2014

Используйте этот идеальный вариант для меня.

CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(@"%@",indexPath);
2 голосов
/ 08 ноября 2015

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

Вот как узнать, какая кнопка была нажата

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

}
...