web-dev-qa-db-fra.com

Comment obtenir UITableViewCell indexPath depuis la cellule?

Comment puis-je, à partir d'une cellule, obtenir sa indexPath dans une UITableView?

J'ai effectué des recherches sur le débordement de pile et sur Google, mais toutes les informations sont inversées. Existe-t-il un moyen d'accéder à la variable superView/UITableView, puis de rechercher la cellule?

Plus d'informations sur le contexte: j'ai deux classes, l'une s'appelle Cue et l'autre CueTableCell (qui est une sous-classe de UITableViewCell) CueTableCell est la représentation visuelle de Cue (les deux classes ont des pointeurs entre elles). Les objets Cue sont dans une liste chaînée et lorsque l'utilisateur exécute une certaine commande, la représentation visuelle (la CueTableCell) de la prochaine Cue doit être sélectionnée. Ainsi, la classe Cue appelle la méthode select sur la prochaine Cue de la liste, qui extrait la UITableView de la cell et appelle sa selectRowAtIndexPath:animated:scrollPosition:, pour laquelle elle a besoin de la indexPath de la UITableViewCell.

63
sinθ
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

Cela facilite la lecture de la documentation , même si cela est considéré par certains comme controversé (voir les commentaires ci-dessous).

La cellule n'a pas d'activité sachant quel est son chemin d'index. Controller doit contenir tout code manipulant des éléments d'interface utilisateur basés sur le modèle de données ou modifiant des données basées sur des interactions d'interface utilisateur. (Voir MVC .)

126
Mundi

Essayez ceci avec votre UITableViewCell: 

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

EDIT: Cela semble ne pas fonctionner avec iOS 8.1.2 et plus. Merci à Chris Prince pour l'avoir signalé. 

25
Pepper

Vous pouvez essayer cette astuce simple: 

sur votre UITableViewCell classe: 

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

et sur votre méthode cellForRowAtIndexPath:

...
[cell setMyCellIndex : indexPath.row]

maintenant, vous pouvez récupérer votre index cellulaire n'importe où

10

Pour adresser ceux qui disent "c'est une mauvaise idée", dans mon cas, mon besoin est que j'ai un bouton sur ma UITableViewCell qui, lorsqu'il est enfoncé, est une transition vers une autre vue. Comme il ne s’agit pas d’une sélection sur la cellule elle-même, [self.tableView indexPathForSelectedRow] ne fonctionne pas.

Cela me laisse deux options:

  1. Stocke l'objet que je dois passer dans la vue dans la cellule de tableau elle-même. Bien que cela fonctionnerait, cela éviterait le fait que je possède une NSFetchedResultsController car je ne veux pas vouloir stocker tous les objets en mémoire, en particulier si la table est longue.
  2. Récupère l'élément du contrôleur d'extraction à l'aide du chemin d'index. Oui, il semble moche que je doive trouver un NSIndexPath par un hack, mais c'est finalement moins cher que de stocker des objets en mémoire.

indexPathForCell: est la méthode correcte à utiliser, mais voici comment je le ferais (ce code est supposé être implémenté dans une sous-classe de 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;
}

P.S. Mon vrai code accède à tout cela à partir de la vue tableau, mais je donne un exemple de la raison pour laquelle une personne pourrait vouloir faire quelque chose comme ceci directement dans la cellule du tableau.

9
mikeho

Pour Swift 

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

La réponse à cette question m'a en fait beaucoup aidé.

J'ai utilisé NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

La sender dans mon cas était une UITableViewCell et provient de la méthode prepareForSegue.

J'ai utilisé ceci parce que je n'avais pas un TableViewControllermais j'avais UITableView property outlet

Je devais trouver le titre de la variable Cell et donc connaître son chemin indexPath.

J'espère que cela aide n'importe qui!

4
Cescy

Sur iOS 11.0, vous pouvez utiliser UITableView.indexPathForRow(at point: CGPoint) -> IndexPath?:

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

Il obtient le point central de la cellule, puis tableView renvoie le chemin indexPath correspondant à ce point. 

2
banan3'14

essayez ceci (cela ne fonctionne que si la table a une seule section et que toutes les cellules ont des hauteurs égales):

//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;
1
m.eldehairy

Swift 4.x

Pour donner accès à ma cellule, j'ai fait quelque chose comme ça:

J'ai une extension de l'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
    }
}

Et puis .. dans ma cellule

class SomeCell: UITableViewCell {

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

C'est tout moi.

Meilleures salutations.

0
LagMaster

Essayez ceci avec votre UITableViewCell:

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