ios - Ottieni clic con il pulsante all'interno di UITableViewCell




objective-c uibutton (10)

Swift 2.2

Devi aggiungere un obiettivo per quel pulsante.

myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)

FunctionName: connesso // ad esempio

E ovviamente devi impostare il tag di quel pulsante da quando lo stai usando.

myButton.tag = indexPath.row

È possibile ottenere questo sottoclasse UITableViewCell. Usalo nel generatore di interfaccia, rilascia un pulsante su quella cella, collegalo via presa e via.

Per ottenere il tag nella funzione connessa:

func connected(sender: UIButton) {
    let buttonTag = sender.tag
    // Do any additional setup
}

Ho un controller di visualizzazione con una vista tabella e un pennino separato per il modello di cella di tabella. Il modello di cella ha alcuni pulsanti. Voglio accedere al clic del pulsante insieme all'indice della cella cliccata all'interno del controller della vista dove ho definito la vista Tabella.

Quindi ho TableTemplate.m e TableTemplate.xib dove ho UITableView e TableTemplate.h , TableTemplate.m e TableTemplate.xib dove ho definito il pennino. Voglio l'evento click del pulsante con l'indice delle celle in ViewController.m .

Qualsiasi aiuto su come posso farlo?


1) Nel tuo cellForRowAtIndexPath: metodo, assegna tag pulsante come indice:

cell.yourbutton.tag = indexPath.row;

2) Aggiungi target e azione per il tuo pulsante come di seguito:

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

3) Azioni di codice basate su indice come sotto in ViewControler :

-(void)yourButtonClicked:(UIButton*)sender
{
     if (sender.tag == 0) 
     {
         // Your code here
     }
}

Aggiornamenti per più sezioni:

È possibile controllare questo collegamento per rilevare il clic del pulsante nella vista tabella per più righe e sezioni.


Il codice di Tarun non funziona su iOS7, poiché la struttura di UITableViewCell è cambiata e ora avrebbe ottenuto "UITableViewCellScrollView".

Questo post Ottenere UITableViewCell con superview in iOS 7 ha una buona soluzione per creare un loop per trovare la corretta visualizzazione genitore, indipendentemente da eventuali futuri cambiamenti nella struttura. Si riduce alla creazione di un ciclo:

    UIView *superView = [sender superview];
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView) {
        if ([superView isKindOfClass:[UITableViewCell class]]) {
            foundSuperView = superView;
        } else {
            superView = superView.superview;
        }
    }

Il collegamento ha il codice per una soluzione più riutilizzabile, ma dovrebbe funzionare.


Il motivo per cui mi piace la tecnica di seguito perché mi aiuta anche a identificare la sezione del tavolo.

Aggiungi pulsante nella cella cellForRowAtIndexPath:

 UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)];
        [selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun 
    [selectTaskBtn addTarget:self action:@selector(addTask:)   forControlEvents:UIControlEventTouchDown];
[cell addsubview: selectTaskBtn];

Aggiungi evento:

-(void)addTask:(UIButton*)btn
{
    CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     int currentIndex = indexPath.row;
     int tableSection = indexPath.section;
    }
}

Spera questo aiuto


Invece di giocare con i tag, ho adottato un approccio diverso. Reso delegato per la mia sottoclasse di UITableViewCell (OptionButtonsCell) e aggiunto una variabile indexPath. Dal mio pulsante nello storyboard ho collegato @IBAction all'OptionButtonsCell e lì mando il metodo delegate con il giusto indexPath a chiunque sia interessato. Nella cella per il percorso dell'indice ho impostato indexPath corrente e funziona :)

Lascia che il codice parli da solo:

Swift 3 Xcode 8

OptionButtonsTableViewCell.swift

import UIKit
protocol OptionButtonsDelegate{
    func closeFriendsTapped(at index:IndexPath)
}
class OptionButtonsTableViewCell: UITableViewCell {
    var delegate:OptionButtonsDelegate!
    @IBOutlet weak var closeFriendsBtn: UIButton!
    var indexPath:IndexPath!
    @IBAction func closeFriendsAction(_ sender: UIButton) {
        self.delegate?.closeFriendsTapped(at: indexPath)
    }
}

MyTableViewController.swift

class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell
    cell.delegate = self
    cell.indexPath = indexPath
    return cell   
}

func closeFriendsTapped(at index: IndexPath) {
     print("button tapped at index:\(index)")
}

La risposta @Mani è buona, tuttavia i tag di visualizzazione all'interno del contenuto della cella spesso vengono utilizzati per altri scopi. Puoi utilizzare il tag della cella (o il tag contentView della cella):

1) Nel tuo cellForRowAtIndexPath: metodo, assegna il tag della cella come indice:

cell.tag = indexPath.row; // or cell.contentView.tag...

2) Aggiungi target e azione per il tuo pulsante come di seguito:

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

3) Crea un metodo che restituisca una riga del mittente (grazie a @Stenio Ferreira):

- (NSInteger)rowOfSender:(id)sender
{
    UIView *superView = sender.superview;
    while (superView) {
        if ([superView isKindOfClass:[UITableViewCell class]])
            break;
        else
            superView = superView.superview;
    }

    return superView.tag;
}

4) Azioni di codice basate su indice:

-(void)yourButtonClicked:(UIButton*)sender
{
     NSInteger index = [self rowOfSender:sender];
     // Your code here
}

Trovo più semplice creare una sottoclasse del pulsante all'interno della cella (Swift 3):

class MyCellInfoButton: UIButton {
    var indexPath: IndexPath?
}

Nella tua classe di cellule:

class MyCell: UICollectionViewCell {
    @IBOutlet weak var infoButton: MyCellInfoButton!
   ...
}

Nell'origine dati della vista tabella o della raccolta, quando si rimuove la cella, dare al pulsante il suo percorso dell'indice:

cell.infoButton.indexPath = indexPath

Quindi puoi semplicemente inserire questi codici nel tuo controller di visualizzazione tabella:

@IBAction func handleTapOnCellInfoButton(_ sender: MyCellInfoButton) {
        print(sender.indexPath!) // Do whatever you want with the index path!
}

E non dimenticare di impostare la classe del pulsante nel tuo Interface Builder e collegarlo alla funzione handleTapOnCellInfoButton !

modificato:

Utilizzando l'iniezione di dipendenza. Per impostare la chiusura di una chiamata:

class MyCell: UICollectionViewCell {
    var someFunction: (() -> Void)?
    ...
    @IBAction func didTapInfoButton() {
        someFunction?()
    }
}

e iniettare la chiusura nel metodo willDisplay del delegato della vista dell'insieme:

 func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    (cell as? MyCell)?.someFunction = {
        print(indexPath) // Do something with the indexPath.
    }
}

I delegati sono la strada da percorrere.

Come visto con altre risposte usando le viste potrebbe diventare obsoleto. Chi lo sa che domani potrebbe esserci un altro involucro e potrebbe essere necessario usare cell superview]superview]superview]superview] . E se si utilizzano i tag si finirebbe con n numero di condizioni if ​​else per identificare la cella. Per evitare tutti i delegati impostati. (In questo modo creerai una classe di celle riutilizzabile. Puoi utilizzare la stessa classe di celle di una classe base e tutto ciò che devi fare è implementare i metodi delegati).

Per prima cosa abbiamo bisogno di un'interfaccia (protocollo) che verrà utilizzata dalla cella per comunicare i clic del pulsante (delegato). ( È possibile creare un file .h separato per il protocollo e includerlo nel controller della vista tabella e nelle classi di celle personalizzate OPPURE aggiungerlo in una classe di celle personalizzata che verrà comunque inclusa nel controller di visualizzazione tabella )

@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end

Includi questo protocollo in un controller di visualizzazione di celle e tabelle personalizzato. E assicurarsi che il controller della vista tabella confermi questo protocollo.

Nella cella personalizzata crea due proprietà:

@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;

Nel clic del delegato UIButton IBAction: ( Lo stesso può essere fatto per qualsiasi azione nella classe di cella personalizzata che deve essere delegata indietro per visualizzare il controller )

- (IBAction)buttonClicked:(UIButton *)sender {
    if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
        [self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
    }
}

Nella vista tabella controller cellForRowAtIndexPath dopo aver desquamato la cella, impostare le proprietà sopra.

cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.

E implementare il delegato nel controller di visualizzazione tabella:

- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
{
    // Do additional actions as required.
    NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
}

Questo sarebbe l'approccio ideale per ottenere azioni personalizzate dei pulsanti di cella nel controller di visualizzazione tabella.


// Add action in cell for row at index path -tableView

cell.buttonName.addTarget(self, action: #selector(ViewController.btnAction(_:)), for: .touchUpInside)

// Button Action

  @objc func btnAction(_ sender: AnyObject) {



        var position: CGPoint = sender.convert(.zero, to: self.tableView)


        let indexPath = self.tableView.indexPathForRow(at: position)
        let cell: UITableViewCell = tableView.cellForRow(at: indexPath!)! as
        UITableViewCell




}

cell.show.tag=indexPath.row;
     [cell.show addTarget:self action:@selector(showdata:) forControlEvents:UIControlEventTouchUpInside];

-(IBAction)showdata:(id)sender
{
    UIButton *button = (UIButton *)sender;

    UIStoryboard *storyBoard;
    storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    SecondViewController *detailView = [storyBoard instantiateViewControllerWithIdentifier:@"SecondViewController"];

    detailView.string=[NSString stringWithFormat:@"%@",[_array objectAtIndex:button.tag]];

    [self presentViewController:detailView animated:YES completion:nil];

}




uibutton