Ottenere la riga della cella UITableView alla pressione del pulsante


84

Ho un controller tableview che mostra una riga di celle. Ogni cella ha 3 pulsanti. Ho numerato i tag per ogni cella in 1,2,3. Il problema è che non so come trovare su quale cella viene premuto un pulsante. Al momento ricevo il tag del mittente solo quando uno dei pulsanti è stato premuto. C'è un modo per ottenere anche il numero di riga della cella quando si preme un pulsante?

Risposte:


278

Dovresti davvero usare questo metodo invece:

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

Versione Swift:

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

Questo ti darà la indexPathbase sulla posizione del pulsante che è stato premuto. Quindi chiameresti semplicemente cellForRowAtIndexPathse hai bisogno del cellulare o indexPath.rowse hai bisogno del numero di riga.

Se sei paranoico, puoi controllare if (indexPath) ...prima di usarlo nel caso in cui indexPathnon si trovi per quel punto nella vista tabella.

È probabile che tutte le altre risposte non funzionino se Apple decide di modificare la struttura della visualizzazione.


8
questo, un milione di volte. nessuno degli altri ha funzionato, ma questa era perfetta e di gran lunga la soluzione più semplice
ine il

2
Questa risposta funziona perché è la soluzione corretta . Gli altri sono soluzioni alternative. Grazie!
Bruno Philipe

1
Se non hai self.tableview , fai riferimento alla mia risposta su questa pagina.
Ashok

1
Questo ha funzionato per me quando ho capito che il mio mittente era la classe sbagliata. Risolto il problema per cui veniva premuto il pulsante UIB e ora funziona!
lordB8r

1
ricorda solo che il metodo convertPoint:*to*Viewnon lo è convertPoint:*from*View. Ho usato il completamento automatico Xcode e ho finito con il metodo fromView che portava solo a non funzionare ...
tGilani

40

Modifica: questa risposta è obsoleta. Utilizza invece questo metodo


Prova questo:

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

Modifica: se stai usando contentView, usalo invece per buttonCell:

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

1
Non dovresti aggiungere viste secondarie alla cella stessa ma solo alla sua contentViewproprietà, quindi questa soluzione non funziona davvero.

1
Sono d'accordo con @ H2CO3 e inoltre non penso che questo dovrebbe essere fatto facendo riferimento alle supervisioni. Si prega di consultare un modo migliore di seguito: stackoverflow.com/a/16270198/308315
iwasrobbed

@minimalpop puoi cambiare la risposta corretta? per avere una migliore Q / A!
Thomas Besnehard,

Questo non funziona in iOS 7. Usa indexPathForRowAtPoint: risposta sotto
Austin

Ho provato la stessa versione con un UICollectionView e funziona perfettamente. Molte grazie!
Claus

18

Consiglierei questo modo per recuperare indexPath della cella che ha una sottoview personalizzata - ( compatibile con iOS 7 e tutte le versioni precedenti )

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

Anche questo non richiede self.tablview.

Inoltre, nota il codice commentato che è utile se vuoi lo stesso tramite un @selector di UIGestureRecognizer aggiunto alla tua sottoview personalizzata.


E se avessi bisogno di dati trovati in uitableviewcontroller?
iosMentalist

Buona risposta Se hai una barra di ricerca e vuoi sapere quale tabella viene utilizzata al momento, puoi usare anche questa.
Suraj K Thomas

la gerarchia delle celle della tabella è cambiata? potete aiutarmi a capire che cosa è successo e può essere cambiato ulteriormente?
Kamaldeep singh Bhatia

3

Ci sono due modi:

  1. @ H2CO3 ha ragione. Puoi fare ciò che @ user523234 ha suggerito, ma con una piccola modifica, per rispettare UITableViewCellContentView che dovrebbe trovarsi tra UIButton e UITableViewCell. Quindi, per modificare il suo codice:

    - (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. Se crei un UITableViewCell personalizzato (la tua sottoclasse), puoi semplicemente chiamare selfIBAction. È possibile collegare la funzione IBAction al pulsante utilizzando lo storyboard o a livello di codice quando si imposta la cella.

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

2

Presumo che tu aggiunga pulsanti alla cella cellForRowAtIndexPath, quindi quello che farei è creare una sottoclasse di classe personalizzata UIButton, aggiungere un tag chiamato rowNumbere aggiungere quei dati mentre aggiungi il pulsante alla cella.


3
Questo va bene, ma non c'è motivo di creare una sottoclasse UIButtonper questo. tagè una proprietà comune di UIView.
Rob Napier,

Non so cosa stavo pensando e presumo che qualcosa dell'interfaccia utente non sia un'interfaccia utente , grazie per la correzione!
Derek Li

2

Un altro modo semplice:

  • Ottieni il punto di contatto in tableView

  • Quindi ottieni il percorso dell'indice della cella nel punto

  • Il percorso dell'indice contiene l'indice di riga

Il codice è:

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

Swift 3

Nota: questo dovrebbe davvero andare nella risposta accettata sopra, tranne per il fatto che meta disapprova tali modifiche.

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

Due commenti minori:

  1. La funzione predefinita ha il tipo di mittente Any, che non ha convert.
  2. CGPointZero può essere sostituito da CGPoint ()

Funziona perfettamente.

0

Una soluzione potrebbe essere quella di controllare il tag della superview del pulsante o anche più in alto nella gerarchia di visualizzazione (se il pulsante è nella visualizzazione del contenuto della cella).


0

Vorrei condividere il codice in 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

In rapida:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.