Отримання рядка комірки UITableView при натисканні кнопки


84

У мене є контролер tableview, який відображає рядок комірок. Кожна комірка має 3 кнопки. Я пронумерував теги для кожної комірки 1,2,3. Проблема в тому, що я не знаю, як знайти, на якій комірці натискається кнопка. Наразі я отримую тег відправника лише тоді, коли натиснута одна з кнопок. Чи є спосіб отримати номер рядка комірки також при натисканні кнопки?

Відповіді:


278

Натомість вам слід використовувати цей метод:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];

Swift версія:

let buttonPosition = sender.convert(CGPoint(), to:tableView)
let indexPath = tableView.indexPathForRow(at:buttonPosition)

Це дасть вам indexPathбазуватися на положенні натиснутої кнопки. Тоді ви просто зателефонуєте, cellForRowAtIndexPathякщо вам потрібна комірка або indexPath.rowякщо вам потрібен номер рядка.

Якщо ви параноїк, ви можете перевірити, if (indexPath) ...перед тим як використовувати його, на випадок, якщо його indexPathне знайдено для цієї точки на поданні таблиці.

Усі інші відповіді, швидше за все, зірвуться, якщо Apple вирішить змінити структуру подання.


8
це в мільйон разів. жоден з інших не працював, але це було прекрасно , і, безумовно , найпростіше рішення
INE

2
Ця відповідь працює, оскільки вона є правильним рішенням. Інші - обхідні шляхи. Дякую!
Бруно Філіпе

1
У разі , якщо ви НЕ маєте self.tableview , будь ласка , зверніться до мого відповіді на цій сторінці.
Ашок,

1
Це спрацювало для мене, як тільки я зрозумів, що відправник неправильний клас. Виправлено, що натиснута кнопка UIB, і тепер вона працює!
lordB8r

1
тільки пам'ятайте, що метод convertPoint:*to*Viewне є convertPoint:*from*View. Я використовував автозаповнення Xcode і закінчив із методом fromView, що призвів лише до
непрацювання

40

Редагувати: Ця відповідь застаріла. Будь ласка, скористайтеся цим методом


Спробуйте це:

-(void)button1Tapped:(id)sender
{
    UIButton *senderButton = (UIButton *)sender;
    UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
    UITableView* table = (UITableView *)[buttonCell superview];
    NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
    NSInteger rowOfTheCell = [pathOfTheCell row];
    NSLog(@"rowofthecell %d", rowOfTheCell);
}

Редагувати: якщо ви використовуєте contentView, використовуйте це для buttonCell замість цього:

UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;

1
Ви не повинні додавати підпрограми до самої комірки, а лише до її contentViewвластивості - тому це рішення насправді не працює.

1
Я погоджуюсь з @ H2CO3, і я також не думаю, що це слід робити, посилаючись на суперперегляди. Будь ласка , см кращий спосіб нижче: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop Ви можете змінити правильну відповідь? мати краще запитання / відповіді!
Thomas Besnehard

Це не працює в iOS 7. Використовуйте indexPathForRowAtPoint: відповідь нижче
Остін,

Я спробував ту ж версію з UICollectionView і чудово працює. Дуже дякую!
Клаус

18

Я б порекомендував цей спосіб отримати indexPath комірки, який має будь-який власний підпрогляд - ( сумісний з iOS 7, а також усіма попередніми версіями )

-(void)button1Tapped:(id)sender {
//- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer {
//    UIView *parentCell = gestureRecognizer.view.superview;
    UIView *parentCell = sender.superview;

    while (![parentCell isKindOfClass:[UITableViewCell class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentCell = parentCell.superview;
    }

    UIView *parentView = parentCell.superview;

    while (![parentView isKindOfClass:[UITableView class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentView = parentView.superview;
    }


    UITableView *tableView = (UITableView *)parentView;
    NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell];

    NSLog(@"indexPath = %@", indexPath);
}

Це теж не вимагає self.tablview.

Крім того, зверніть увагу на коментований код, який корисний, якщо ви хочете зробити те саме через @selector UIGestureRecognizer, доданий до вашого спеціального підпрогляду.


Що робити, якщо мені потрібні дані, знайдені в uitableviewcontroller?
iosMentalist

Хороша відповідь. Якщо у вас є панель пошуку і ви хочете знати, яка таблиця використовується на даний момент, ви також можете використовувати її.
Suraj K Thomas

змінено ієрархію комірок таблиці? Ви можете допомогти мені зрозуміти, що відбулося, і чи можна змінити далі?
Kamaldeep singh Bhatia

3

Є два шляхи:

  1. @ H2CO3 має рацію. Ви можете зробити те, що запропонував @ user523234, але з невеликою зміною, щоб поважати UITableViewCellContentView, який повинен знаходитись між UIButton і UITableViewCell. Отже, щоб змінити його код:

    - (IBAction)button1Tapped:(id)sender
    {
        UIButton *senderButton = (UIButton *)sender;
        UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview;
        UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview;
        UITableView* tableView = (UITableView *)tableViewCell.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    
  2. Якщо ви створюєте власний UITableViewCell (власний підклас), ви можете просто зателефонувати selfв IBAction. Ви можете прив’язати функцію IBAction до своєї кнопки за допомогою розкадрування або програмно, коли ви налаштовуєте комірку.

    - (IBAction)button1Tapped:(id)sender
    {
        UITableView* tableView = (UITableView *)self.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    

2

Я припускаю, що ви додаєте кнопки до комірки cellForRowAtIndexPath, тоді я б створив власний підклас класу UIButton, додав тег, що викликається rowNumber, і додав ці дані під час додавання кнопки до комірки.


3
Це добре, але немає підстав створювати для нього підклас UIButton. tagє спільною властивістю UIView.
Роб Нейпір,

Не знаю, про що я думав, і вважаю, що інтерфейс користувача щось не є інтерфейсом , дякую за виправлення!
Дерек Лі

2

Ще один простий спосіб:

  • Отримати сенс дотику в tableView

  • Потім отримайте індексний шлях комірки в точці

  • Шлях індексу містить індекс рядка

Код:

- (void)buttonTapped:(id)sender {
    UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender;
    CGPoint point = [tap locationInView:theTableView];

    NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point];

    NSInteger theRowIndex = theIndexPath.row;
    // do your stuff here
    // ...
}

1

Стрімкий 3

Примітка: Це дійсно повинно йти у прийнятій відповіді вище, за винятком того, що мета хмуриться після таких редагувань.

@IBAction func doSomething(_ sender: UIButton) {
   let buttonPosition = sender.convert(CGPoint(), to: tableView)
   let index = tableView.indexPathForRow(at: buttonPosition)
}

Два незначні коментарі:

  1. Функція за замовчуванням має тип відправника як Any, який не має перетворення.
  2. CGPointZero можна замінити на CGPoint ()

Працює ідеально.

0

Одним із рішень може бути перевірка тегу суперперегляду кнопки або навіть вище в ієрархії подання (якщо кнопка знаходиться у поданні вмісту комірки).


0

Я хотів би швидко поділитися кодом -

extension UITableView
{
    func indexPathForCellContainingView(view1:UIView?)->NSIndexPath?
    {
        var view = view1;
        while view != nil {
            if (view?.isKindOfClass(UITableViewCell) == true)
            {
                return self.indexPathForCell(view as! UITableViewCell)!
            }
            else
            {
                view = view?.superview;
            }
        }
        return nil
    }
}

0

Швидко:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.