Wie bekomme ich UITableViewCell indexPath aus der Zelle?

75

Wie komme ich aus einer Zelle indexPathin eine UITableView?

Ich habe nach Stapelüberlauf und Google gesucht, aber alle Informationen sind umgekehrt. Gibt es eine Möglichkeit, auf das superView/ zuzugreifen UITableViewund dann nach der Zelle zu suchen?

Weitere Informationen zum Kontext: Ich habe zwei Klassen, eine heißt Cueund eine heißt CueTableCell(eine Unterklasse von UITableViewCell) CueTableCellist die visuelle Darstellung von Cue(beide Klassen haben Zeiger aufeinander). CueObjekte befinden sich in einer verknüpften Liste, und wenn der Benutzer einen bestimmten Befehl ausführt, muss die visuelle Darstellung (der CueTableCell) des nächsten Cueausgewählt werden. Die CueKlasse ruft also die selectMethode für die nächste Cuein der Liste auf, die die UITableViewvon der abruft cellund ihre aufruft selectRowAtIndexPath:animated:scrollPosition:, für die sie die indexPathvon benötigt UITableViewCell.

sinθ
quelle
2
Genau wie Ihre andere Frage zum Abrufen UITableViewaus einer Zelle - warum? Dies scheint ein Codegeruch einer schlechten Entwurfsentscheidung zu sein - es gibt nicht viele legitime Anwendungsfälle für eine Zelle, um zu wissen, ob es sich um indexPath handelt oder ob es auf dem Bildschirm angezeigt wird oder nicht.
Pauls
Ich stimme dem Kommentar von Paul zu. Sie sollten angeben, warum Sie dies tun möchten, da das, was Sie versuchen, wahrscheinlich eine schlechte Idee ist.
Rdelmar
@ Paul.s Ich habe das Design meines Programms in der Frage gepostet. Es kann eine schlechte Programmierpraxis sein. In diesem Fall wäre es sehr hilfreich, wenn Sie eine Alternative vorschlagen könnten. Ich bin sehr neu in Kakao und relativ neu in der Programmierung im Allgemeinen.
sinθ
Es ist erwähnenswert, dass indexPathsForVisibleRows vorhanden ist. Dies ist wichtig , wenn Sie in einer Schriftrolle wissen möchten, wo Sie sich befinden.
Fattie

Antworten:

137
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

Es hilft beim Lesen der UITableView-Dokumentation , auch wenn dies von einigen als kontrovers angesehen wird (siehe Kommentare unten).

Die Zelle hat kein Geschäft damit, ihren Indexpfad zu kennen. Der Controller sollte Code enthalten, der UI-Elemente basierend auf dem Datenmodell manipuliert oder Daten basierend auf UI-Interaktionen ändert. (Siehe MVC .)

Mundi
quelle
41
Es hilft, wenn Sie die Frage lesen. Dies ist von einer UITableViewCell, die keine tableView-Eigenschaft hat (und von allen Konten nicht sollte).
voidref
14
@voidref Es hilft auch über die Frage nachzudenken ;-). Die Zelle hat kein Geschäft damit, ihren Indexpfad zu kennen. Dieser Code sollte sich also in der Steuerung befinden. Hintergrundinformationen zu MVC finden Sie unter Kakaokernkompetenzen .
Mundi
2
Es spielt keine Rolle, ob es von Anfang an offensichtlich war, dass die Person die richtige Antwort benötigt.
JDOG
11
Beantwortet die ursprüngliche Frage nicht. Es gibt Zeiten, in denen eine Zelle ihren Pfad kennen muss. Wenn Sie beispielsweise eine Wischaktion für eine untergeordnete Zelle implementiert haben, müssen Sie dieser übergeordneten Ansicht möglicherweise mitteilen, welche Zelle derzeit gewischt wird. Eine Möglichkeit wäre, dass eine Methode in der übergeordneten Ansicht die tableView-Zellen durchläuft und eine in der Zelle festgelegte iVar überprüft. Ein besserer Weg wäre, die Zelle dazu zu bringen, die Elternansicht über eine Delegatmethode über ihren Indexpfad zu informieren ... und daher muss die Zelle wissen, dass es sich um den Indexpfad handelt. Also Mundi, besser die Frage beantworten und dann deinen Standpunkt klarstellen.
Wuf810
4
Der Indexpfad ist der "Klebstoff" zwischen Zellen und Datenmodell, gehört also in die Steuerung. Der lange Kommentar oben ist sachlich falsch. @ wuf810 ... da der Controller die Beziehung zwischen Zelle und Indexpfad kennt, tut (und sollte) die Zelle dies nicht.
Mundi
24

Versuchen Sie dies mit Ihrer UITableViewCell:

NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell: self];

BEARBEITEN: Scheint unter iOS 8.1.2 und höher nicht zu funktionieren. Vielen Dank an Chris Prince für den Hinweis.

Pfeffer
quelle
7
Unter iOS 8.1.2 ist die Übersicht einer Tabellenansichtszelle vom Typ UITableViewWrapperView. Die Übersicht davon ist vom Typ Tabellenansicht. Aber ich denke, wir betreten hier gefährlichen Boden ...
Chris Prince
2
Alles geht zurück auf "Die Zelle hat nichts damit zu tun, ihren Indexpfad zu kennen." Streit. Der Zugriff auf die Übersicht ist fast immer ein Hack und es ist nicht überraschend, dass er nach einer Weile nicht mehr funktioniert.
Fatuhoku
Völlig richtig, Fatuhoku, es ist nicht Sache der Zelle, den
Indexpfad
11

Sie können diesen einfachen Tipp ausprobieren:

in deiner UITableViewCellKlasse:

@property NSInteger myCellIndex; //or add directly your indexPath 

und zu Ihrer cellForRowAtIndexPathMethode:

...
[cell setMyCellIndex : indexPath.row]

Jetzt können Sie Ihren Zellenindex überall abrufen

AITAALI_ABDERRAHMANE
quelle
4
Sie müssen daran denken, diese Informationen manuell zu aktualisieren, nachdem Sie Zellen neu angeordnet oder gelöscht haben.
Konrad
10

Um diejenigen anzusprechen, die sagen "das ist eine schlechte Idee" , muss ich in meinem Fall einen Knopf auf meinem haben UITableViewCell, der beim Drücken einen Übergang zu einer anderen Ansicht darstellt. Da dies keine Auswahl in der Zelle selbst ist, [self.tableView indexPathForSelectedRow]funktioniert dies nicht.

Dies lässt mir zwei Möglichkeiten:

  1. Speichern Sie das Objekt, das ich in die Ansicht übergeben muss, in der Tabellenzelle. Während dies funktionieren würde, würde es den Punkt, an dem ich eine habe, zunichte machen, NSFetchedResultsControllerweil ich nicht alle Objekte im Speicher speichern möchte, insbesondere wenn die Tabelle lang ist.
  2. Rufen Sie das Element über den Indexpfad vom Abrufcontroller ab. Ja, es scheint hässlich, dass ich das NSIndexPathdurch einen Hack herausfinden muss , aber es ist letztendlich billiger als das Speichern von Objekten im Speicher.

indexPathForCell:ist die richtige Methode, aber hier ist, wie ich es machen würde (es wird angenommen, dass dieser Code in einer Unterklasse von implementiert ist UITableViewCell:

// uses the indexPathForCell to return the indexPath for itself
- (NSIndexPath *)getIndexPath {
    return [[self getTableView] indexPathForCell:self];
}

// retrieve the table view from self   
- (UITableView *)getTableView {
    // get the superview of this class, note the camel-case V to differentiate
    // from the class' superview property.
    UIView *superView = self.superview;

    /*
      check to see that *superView != nil* (if it is then we've walked up the
      entire chain of views without finding a UITableView object) and whether
      the superView is a UITableView.
    */
    while (superView && ![superView isKindOfClass:[UITableView class]]) {
        superView = superView.superview;
    }

    // if superView != nil, then it means we found the UITableView that contains
    // the cell.
    if (superView) {
        // cast the object and return
        return (UITableView *)superView;
    }

    // we did not find any UITableView
    return nil;
}

PS Mein echter Code greift über die Tabellenansicht auf all dies zu, aber ich gebe ein Beispiel dafür, warum jemand so etwas direkt in der Tabellenzelle tun möchte.

mikeho
quelle
10
  1. Fügen Sie eine schwache tableView-Eigenschaft wie folgt in die .h-Datei der Zelle ein:

    @property (weak,nonatomic)UITableView *tableView;

  2. Weisen Sie die Eigenschaft in der cellForRowAtIndex-Methode wie folgt zu:

    cell.tableView = tableView;

  3. Wo immer Sie den Indexpfad der Zelle benötigen:

    NSIndexPath *indexPath = [cell.tableView indexPathForCell:cell];

Chanchal Raj
quelle
Dies funktioniert, weil wir nur einen Zeiger auf die tableView selbst speichern. Ist indexPathForCell jedoch zuverlässig? Ich dachte, dies liefert nur indexPath von sichtbaren Zellen nicht?
JCPennypincher
6

Für schnell

let indexPath :NSIndexPath? = (self.superview.superview as! UITableView)?.indexPathForCell(self)
Gevorg Ghukasyan
quelle
4

Die Antwort auf diese Frage hat mir sehr geholfen.

ich benutzte NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

Das war senderin meinem Fall ein UITableViewCellund kommt von der prepareForSegueMethode.

Ich habe das benutzt, weil ich kein hatte , TableViewControlleraber ich hatteUITableView property outlet

Ich musste den Titel des herausfinden Cellund daher den Indexpfad davon kennen.

Hoffe das hilft jedem!

Cescy
quelle
4

Unter iOS 11.0 können Sie Folgendes verwenden UITableView.indexPathForRow(at point: CGPoint) -> IndexPath?:

if let indexPath = tableView.indexPathForRow(at: cell.center) {
    tableView.selectRow
    (at: indexPath, animated: true, scrollPosition: .middle)
}

Es erhält den Mittelpunkt der Zelle und dann gibt die Tabellenansicht den Indexpunkt zurück, der diesem Punkt entspricht.

banan3'14
quelle
1

Versuchen Sie dies (es funktioniert nur, wenn die tableView nur einen Abschnitt hat und alle Zellen die gleiche Höhe haben):

//get current cell rectangle relative to its superview
CGRect r = [self convertRect:self.frame toView:self.superview];

//get cell index
int index = r.origin.y / r.size.height;
m.eldehairy
quelle
0

Versuchen Sie dies mit Ihrer UITableViewCell:

NSIndexPath *indexPath = [(UITableView *)self.superview.superview indexPathForCell:self];
Yogesh Kumar
quelle
-1

Swift 4.x.

Um Zugang zu meiner Zelle zu erhalten, habe ich Folgendes getan:

Ich habe eine Erweiterung des UIView:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

Und dann .. in meiner Zelle Klasse:

class SomeCell: UITableViewCell {

    func someMethod() {
        if let myViewController = self.parentViewController as? CarteleraTableViewController {
            let indexPath : IndexPath = (myViewController.tableView).indexPath(for: self)!
            print(indexPath)
        }
    }
}

Das ist alles von mir.

Freundliche Grüße.

Andres Paladines
quelle