Pobieranie wiersza komórki UITableView po naciśnięciu przycisku


84

Mam kontroler tableview, który wyświetla wiersz komórek. Każda komórka ma 3 przyciski. Ponumerowałem tagi dla każdej komórki na 1, 2, 3. Problem w tym, że nie wiem, jak sprawdzić, na której komórce przycisk jest naciskany. Obecnie otrzymuję tag nadawcy dopiero po naciśnięciu jednego z przycisków. Czy istnieje sposób, aby uzyskać numer wiersza komórki również po naciśnięciu przycisku?

Odpowiedzi:


278

Zamiast tego naprawdę powinieneś używać tej metody:

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

Wersja Swift:

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

To da ci podstawę w indexPathoparciu o położenie przycisku, który został naciśnięty. Wtedy po prostu zadzwonisz, cellForRowAtIndexPathjeśli potrzebujesz komórki lub indexPath.rowjeśli potrzebujesz numeru wiersza.

Jeśli masz paranoję, możesz sprawdzić if (indexPath) ...przed użyciem, na wypadek gdyby indexPathnie znaleziono tego punktu w widoku tabeli.

Wszystkie inne odpowiedzi prawdopodobnie się zepsują, jeśli Apple zdecyduje się zmienić strukturę widoku.


8
to milion razy. żadne inne nie działało, ale to było doskonałe i zdecydowanie najprostsze rozwiązanie
ine

2
Ta odpowiedź działa, ponieważ jest to poprawne rozwiązanie. Pozostałe to obejścia. Dzięki!
Bruno Philipe

1
Jeśli nie masz self.tableview , zapoznaj się z moją odpowiedzią na tej stronie.
Ashok,

1
To zadziałało, gdy zdałem sobie sprawę, że mój nadawca to niewłaściwa klasa. Naprawiono to, że jest wciśnięty przycisk UIButton, a teraz działa!
lordB8r

1
pamiętaj tylko, że metoda convertPoint:*to*Viewnie jest convertPoint:*from*View. Kiedyś Xcode autouzupełniania i skończyło się metoda fromView prowadząc tylko nie działa ...
tGilani

40

Edycja: ta odpowiedź jest nieaktualna. Zamiast tego użyj tej metody


Spróbuj tego:

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

Edycja: Jeśli używasz contentView, użyj tego zamiast buttonCell:

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

1
Nie powinieneś dodawać podglądów podrzędnych do samej komórki, ale tylko do jej contentViewwłaściwości - więc to rozwiązanie tak naprawdę nie działa.

1
Zgadzam się z @ H2CO3 i uważam, że nie powinno się tego robić poprzez odwoływanie się do superwizorów. Zobacz lepszy sposób poniżej: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop czy możesz zmienić poprawną odpowiedź? mieć lepsze Q / A!
Thomas Besnehard

To nie działa w iOS 7. Użyj indexPathForRowAtPoint: odpowiedź poniżej
Austin

Wypróbowałem tę samą wersję z UICollectionView i działa doskonale. Wielkie dzięki!
Claus

18

Poleciłbym w ten sposób pobrać indexPath komórki, która ma dowolny niestandardowy podgląd - ( kompatybilny z iOS 7, jak również wszystkimi poprzednimi wersjami )

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

To też nie wymaga self.tablview.

Zwróć również uwagę na skomentowany kod, który jest przydatny, jeśli chcesz to samo za pomocą @selektora UIGestureRecognizer dodanego do niestandardowego widoku podrzędnego.


A jeśli potrzebuję danych znalezionych w kontrolerze uitableview?
iosMentalist

Dobra odpowiedź. Jeśli masz pasek wyszukiwania i chciałbyś wiedzieć, który stół jest obecnie używany, możesz go również użyć.
Suraj K Thomas

zmieniła się hierarchia komórek tabeli? czy możesz mi pomóc zrozumieć, jakie zmiany zaszły i czy można to zmienić dalej?
Kamaldeep singh Bhatia

3

Istnieją dwa sposoby:

  1. @ H2CO3 ma rację. Możesz zrobić to, co sugerował @ user523234, ale z niewielką zmianą, aby uszanować UITableViewCellContentView, który powinien znaleźć się między UIButton i UITableViewCell. Aby zmodyfikować jego kod:

    - (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. Jeśli utworzysz niestandardową UITableViewCell (własną podklasę), możesz po prostu wywołać selfIBAction. Możesz połączyć funkcję IBAction z przyciskiem za pomocą scenorysu lub programowo podczas konfigurowania komórki.

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

2

Zakładam, że dodajesz przyciski do komórki w cellForRowAtIndexPath, a następnie utworzę podklasę niestandardowej klasy UIButton, dodasz tag o nazwie rowNumberi dołączasz te dane podczas dodawania przycisku do komórki.


3
To jest w porządku, ale nie ma powodu, aby tworzyć UIButtondla niego podklasę . tagjest wspólną własnością UIView.
Rob Napier

Nie wiem, o czym myślałem i zakładam, że coś w interfejsie użytkownika nie jest interfejsem użytkownika , dzięki za korektę!
Derek Li

2

Inny prosty sposób:

  • Uzyskaj punkt kontaktu w tableView

  • Następnie pobierz ścieżkę indeksu komórki w punkcie

  • Ścieżka indeksu zawiera indeks wiersza

Kod to:

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

Szybki 3

Uwaga: To powinno naprawdę znaleźć się w zaakceptowanej odpowiedzi powyżej, z wyjątkiem tego, że meta marszczy brwi na takie zmiany.

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

Dwie drobne uwagi:

  1. Domyślna funkcja ma typ nadawcy Any, który nie ma konwersji.
  2. CGPointZero można zastąpić CGPoint ()

Działa świetnie.

0

Jednym z rozwiązań mogłoby być sprawdzenie tagu podglądu przycisku lub nawet wyżej w hierarchii widoku (jeśli przycisk znajduje się w widoku zawartości komórki).


0

Chciałbym szybko udostępnić kod -

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

Szybko:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.