web-dev-qa-db-fra.com

Obtention de la rangée de cellules UITableView lors d’une pression sur un bouton

J'ai un contrôleur de table qui affiche une rangée de cellules. Chaque cellule a 3 boutons. J'ai numéroté les étiquettes pour chaque cellule pour être 1,2,3. Le problème est que je ne sais pas comment trouver sur quelle cellule un bouton est enfoncé. Je ne reçois actuellement la balise de l'expéditeur que lorsque l'un des boutons a été actionné. Existe-t-il un moyen d’obtenir le numéro de ligne de la cellule aussi bien quand on appuie sur un bouton?

84
minimalpop

Vous devriez vraiment utiliser cette méthode à la place:

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

Version rapide:

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

Cela vous donnera la indexPath en fonction de la position du bouton sur lequel vous avez appuyé. Ensuite, vous appelez simplement cellForRowAtIndexPath si vous avez besoin de la cellule ou indexPath.row si vous avez besoin du numéro de ligne.

Si vous êtes paranoïaque, vous pouvez vérifier if (indexPath) ... avant de l'utiliser au cas où la variable indexPath ne serait pas trouvée pour ce point dans la vue tableau.

Toutes les autres réponses risquent de ne pas aboutir si Apple décide de modifier la structure de la vue.

276
iwasrobbed

Edit: Cette réponse est obsolète. Veuillez utiliser cette méthode à la place


Essaye ça:

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

Edit: Si vous utilisez contentView, utilisez plutôt ceci pour buttonCell:

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

Je recommanderais cette méthode pour extraire indexPath de la cellule qui a une sous-vue personnalisée - (compatible avec iOS 7 ainsi que toutes les versions précédentes)

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

Cela ne nécessite pas non plus self.tablview.

Notez également le code commenté, qui est utile si vous souhaitez que le même élément soit ajouté à @selector of UIGestureRecognizer ajouté à votre sous-vue personnalisée.

17
Ashok

Il y a deux manières:

  1. @ H2CO3 a raison. Vous pouvez faire ce que @ user523234 a suggéré, mais avec une petite modification, de respecter le UITableViewCellContentView qui doit se trouver entre UIButton et UITableViewCell. Donc pour modifier son 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. Si vous créez une UITableViewCell personnalisée (votre propre sous-classe), vous pouvez simplement appeler self dans IBAction. Vous pouvez lier la fonction IBAction à votre bouton en utilisant le storyboard ou par programme lorsque vous configurez la cellule.

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

Je suppose que vous ajoutez des boutons à la cellule dans cellForRowAtIndexPath, ce que je ferais alors: créer une sous-classe de classe personnalisée UIButton, ajouter un tag appelé rowNumber et ajouter ces données tout en ajoutant un bouton à une cellule. 

2
Derek Li

Un autre moyen simple:

  • Obtenez le point de contact dans tableView

  • Puis obtenir le chemin d'index de la cellule au point

  • Le chemin de l'index contient l'index de la ligne

Le code est:

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

Swift 3

Note: Ceci devrait vraiment aller dans la réponse acceptée ci-dessus, sauf que méta fronce les sourcils lors de telles modifications.

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

Deux commentaires mineurs:

  1. La fonction par défaut a le type d’expéditeur Any, ce qui n’est pas converti.
  2. CGPointZero peut être remplacé par CGPoint ()
1
Roy Falk

Je voudrais partager le code dans Swift -

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
Anupam Mishra

Une solution pourrait consister à vérifier la balise de la vue d'ensemble du bouton ou même plus haut dans la hiérarchie de la vue (si le bouton est dans la vue du contenu de la cellule).

0
Jakob W

En rapide:

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