Zeile der UITableView-Zelle beim Drücken der Taste abrufen

84

Ich habe einen Tableview-Controller, der eine Reihe von Zellen anzeigt. Jede Zelle hat 3 Tasten. Ich habe die Tags für jede Zelle mit 1,2,3 nummeriert. Das Problem ist, dass ich nicht weiß, in welcher Zelle eine Taste gedrückt wird. Ich erhalte derzeit nur das Absender-Tag, wenn eine der Tasten gedrückt wurde. Gibt es eine Möglichkeit, die Zellenzeilennummer auch zu erhalten, wenn eine Taste gedrückt wird?

Minimalpop
quelle

Antworten:

278

Sie sollten stattdessen wirklich diese Methode verwenden:

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

Schnelle Version:

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

Dadurch erhalten Sie die indexPathbasierend auf der Position der Taste, die gedrückt wurde. Dann würden Sie einfach anrufen, cellForRowAtIndexPathwenn Sie die Zelle benötigen oder indexPath.rowwenn Sie die Zeilennummer benötigen.

Wenn Sie paranoid sind, können Sie dies überprüfen, if (indexPath) ...bevor Sie es verwenden, falls das indexPathfür diesen Punkt in der Tabellenansicht nicht gefunden wird.

Alle anderen Antworten werden wahrscheinlich nicht funktionieren, wenn Apple beschließt, die Ansichtsstruktur zu ändern.

Ich wurde ausgeraubt
quelle
8
das millionenfach. keines der anderen gearbeitet, aber das war perfekt und mit Abstand die einfachste Lösung
ine
2
Diese Antwort funktioniert, weil es die richtige Lösung ist. Die anderen sind Problemumgehungen. Vielen Dank!
Bruno Philipe
1
Falls Sie keine self.tableview haben, lesen Sie bitte meine Antwort auf dieser Seite.
Ashok
1
Dies funktionierte für mich, als mir klar wurde, dass mein Absender die falsche Klasse war. Es wurde behoben, dass der UIButton gedrückt wurde, und jetzt funktioniert es!
Lord B8r
1
Denken Sie daran, die Methode ist convertPoint:*to*Viewnicht convertPoint:*from*View. Ich habe Xcode Autocomplete verwendet und am Ende die fromView-Methode verwendet, die nur dazu führte, dass sie nicht funktionierte ...
tGilani
40

Bearbeiten: Diese Antwort ist veraltet. Bitte verwenden Sie stattdessen diese Methode


Versuche dies:

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

Bearbeiten: Wenn Sie contentView verwenden, verwenden Sie dies stattdessen für buttonCell:

UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;
user523234
quelle
1
Sie sollten der Zelle selbst keine Unteransichten hinzufügen, sondern nur deren contentViewEigenschaft - daher funktioniert diese Lösung nicht wirklich.
1
Ich stimme @ H2CO3 zu und denke auch nicht, dass dies durch Verweisen auf Übersichten erfolgen sollte. Bitte sehen Sie einen besseren Weg unten: stackoverflow.com/a/16270198/308315
iwasrobbed
@minimalpop kannst du bitte die richtige antwort ändern? um ein besseres Q / A zu haben!
Thomas Besnehard
Dies funktioniert nicht in iOS 7. Verwenden Sie indexPathForRowAtPoint: Antwort unten
Austin
Ich habe die gleiche Version mit einem UICollectionView ausprobiert und funktioniert einwandfrei. Vielen Dank!
Claus
18

Ich würde diesen Weg empfehlen, um indexPath einer Zelle abzurufen, die eine benutzerdefinierte Unteransicht hat - ( kompatibel mit iOS 7 sowie allen vorherigen Versionen )

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

Dies erfordert auch self.tablviewnicht.

Beachten Sie auch den kommentierten Code, der nützlich ist, wenn Sie dasselbe über einen @selector von UIGestureRecognizer wünschen, der Ihrer benutzerdefinierten Unteransicht hinzugefügt wurde.

Ashok
quelle
Was ist, wenn ich Daten im uitableviewcontroller benötige?
iosMentalist
Gute Antwort. Wenn Sie eine Suchleiste haben und wissen möchten, welche Tabelle gerade verwendet wird, können Sie diese auch verwenden.
Suraj K Thomas
Tabellenzellenhierarchie geändert? Können Sie mir helfen zu verstehen, welche Änderungen stattgefunden haben, und können sie weiter geändert werden?
Kamaldeep singh Bhatia
3

Es gibt zwei Möglichkeiten:

  1. @ H2CO3 ist richtig. Sie können das tun, was @ user523234 vorgeschlagen hat, aber mit einer kleinen Änderung, um die UITableViewCellContentView zu berücksichtigen, die zwischen dem UIButton und der UITableViewCell liegen sollte. So ändern Sie seinen Code:

    - (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. Wenn Sie eine benutzerdefinierte UITableViewCell (Ihre eigene Unterklasse) erstellen, können Sie einfach selfdie IBAction aufrufen. Sie können die IBAction-Funktion mithilfe des Storyboards oder programmgesteuert beim Einrichten der Zelle mit Ihrer Schaltfläche verknüpfen.

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

Ich cellForRowAtIndexPathgehe davon aus, dass Sie der Zelle Schaltflächen hinzufügen. Dann würde ich eine benutzerdefinierte Klassenunterklasse erstellen UIButton, ein Tag mit dem Namen hinzufügen rowNumberund diese Daten anhängen, während Sie der Zelle eine Schaltfläche hinzufügen.

Derek Li
quelle
3
Dies ist in Ordnung, aber es gibt keinen Grund, eine Unterklasse dafür zu erstellen UIButton. tagist eine gemeinsame Eigenschaft von UIView.
Rob Napier
Ich weiß nicht, was ich gedacht habe und gehe davon aus, dass die Benutzeroberfläche keine Benutzeroberfläche ist. Vielen Dank für die Korrektur!
Derek Li
2

Ein anderer einfacher Weg:

  • Holen Sie sich den Touchpoint in tableView

  • Dann erhalten Sie den Indexpfad der Zelle am Punkt

  • Der Indexpfad enthält den Zeilenindex

Der Code lautet:

- (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
    // ...
}
vietstone
quelle
1

Swift 3

Hinweis: Dies sollte wirklich in der oben akzeptierten Antwort enthalten sein , mit der Ausnahme, dass Meta bei solchen Änderungen die Stirn runzelt.

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

Zwei kleine Kommentare:

  1. Die Standardfunktion hat den Absendertyp Any, der nicht konvertiert werden kann.
  2. CGPointZero kann durch CGPoint () ersetzt werden
Roy Falk
quelle
Funktioniert perfekt.
0

Eine Lösung könnte darin bestehen, das Tag der Übersicht der Schaltfläche oder sogar höher in der Ansichtshierarchie zu überprüfen (wenn sich die Schaltfläche in der Inhaltsansicht der Zelle befindet).

Jakob W.
quelle
0

Ich möchte Code in Kürze teilen -

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
    }
}
Anupam Mishra
quelle
0

In Kürze:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
Leszek Szary
quelle