web-dev-qa-db-fra.com

UITableViewCell Boutons avec action

Bonjour, j'ai une UITableViewCell personnalisée avec trois boutons pour gérer une fonction de panier, ainsi que des boutons Plus, Moins et Supprimer et j'ai besoin de savoir quelle cellule a été touchée. 

J'ai déjà essayé d'utiliser la "solution d'étiquette" mais cela ne fonctionne pas à cause du cycle de vie des cellules. 

Quelqu'un peut-il m'aider s'il vous plaît à trouver une solution?

Merci d'avance 

6
jack87

Je résolvais cela en utilisant une méthode de délégation de cellule dans la sous-classe de UITableViewCell.

Rapide vue d'ensemble:

1) Créer un protocole

protocol YourCellDelegate : class {
    func didPressButton(_ tag: Int)
}

2) Sous-classe votreUITableViewCell(si vous ne l'avez pas déjà fait):

class YourCell : UITableViewCell
{
     var cellDelegate: YourCellDelegate?   
      @IBOutlet weak var btn: UIButton!
    // connect the button from your cell with this method
    @IBAction func buttonPressed(_ sender: UIButton) {
        cellDelegate?.didPressButton(sender.tag)
    }         
    ...
}

3) Laisser votre vue contrôleur se conformer au protocole YourCellDelegate mis en œuvre ci-dessus.

class YourViewController: ..., YourCellDelegate {  ... }

4) Définit un délégué , après la définition de la cellule (pour la réutilisation).

let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.cellDelegate = self
cell.btn.tag = indexPath.row

5) Dans le même contrôleur (où est votre délégué/source de données UITableView implémenté), mettez une méthode de YourCellDelegate protocole .

func didPressButton(_ tag: Int) {
     print("I have pressed a button with a tag: \(tag)")
}

Désormais, votre solution ne dépend pas des tags/numéros. Vous pouvez ajouter autant de boutons que vous le souhaitez, vous êtes donc prêt à obtenir une réponse via un délégué, quel que soit le nombre de boutons que vous souhaitez installer.

Cette solution de délégation de protocole est préférable dans la logique iOS et peut être utilisée pour d'autres éléments de la cellule de tableau, tels que UISwitch, UIStepper, etc.

42
pedrouan

Je suis tombé sur le même problème après avoir rendu les IBOutlets privés, comme l'a largement suggéré la communauté.

Voici ma solution:

<Dans votre classe de cellule>

protocol YourCellDelegate: class {
    func didTapButton(_ sender: UIButton)
}

class YourCell: UITableViewCell {

    weak var delegate: YourCellDelegate?

    @IBAction func buttonTapped(_ sender: UIButton) {
        delegate?.didTapButton(sender)
    }
}

<Dans votre ViewController>

class ViewController: UIViewController, YourCellDelegate {

    func didTapButton(_ sender: UIButton) {
        if let indexPath = getCurrentCellIndexPath(sender) {
            item = items[indexPath.row]
        }
    }

    func getCurrentCellIndexPath(_ sender: UIButton) -> IndexPath? {
        let buttonPosition = sender.convert(CGPoint.zero, to: tableView)
        if let indexPath: IndexPath = tableView.indexPathForRow(at: buttonPosition) {
            return indexPath
        }
        return nil
    }
}
11
Frederico

Vous pouvez également obtenir l'index de bouton sélectionné en utilisant la hiérarchie de la vue tableViewCell.

En utilisant les étapes suivantes:

  1. ajoutez le sélecteur au chemin cellForRowAtIndexpath de la vue table:

    btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
    

2 récupérez indexPath en utilisant la méthode suivante: 

func buttonPressed(_ sender: AnyObject) {
        let button = sender as? UIButton
        let cell = button?.superview?.superview as? UITableViewCell
        let indexPath = tblview.indexPath(for: cell!)
        print(indexPath?.row)
    }
3
KKRocks

Swift 4. *

Cela peut être fait comme suit de la même façon, peu de codage et de délégation, simple et facile.

Mettez le code suivant dans cellForItemAt pour UICollectionView ou dans cellForRowAt pour UITableView 

cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)

Et votre méthode sera 

@objc func buttonSelected(sender: UIButton){
    print(sender.tag)
}

C'est tout.

2
Abhishek Mitra

@pedrouan est génial, sauf que vous utilisez l'option tag du bouton. Dans de nombreux cas, lorsque vous définissez le bouton sur tableViewCell, ces boutons modifieront la source de données tableView (par exemple, InsertRow, DeleteRow). 

Mais la balise du bouton n'est pas mise à jour même si une nouvelle cellule est inserted ou deleted. Par conséquent, il est préférable de passer la variable cell elle-même en tant que paramètre plutôt que de passer la variable tag du bouton au paramètre.

Voici mon exemple pour y parvenir.

Votre ExampleCell

protocol ExampleCellDelegate: class {
    func didTapButton(cell: ExampleCell)
}

class ExampleCell: UITableViewCell {

    weak var cellDelegate: ExampleCellDelegate?

    @IBAction func btnTapped(_ sender: UIButton) {
        cellDelegate?.didTapButton(cell: self)
    }
}

Votre ViewController

class ViewController: ExampleCellDelegate {
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as? ExampleCell {

            cell.cellDelegate = self
            return cell
        }
        return UITableViewCell()
    }

    func didTapButton(cell: ExampleCell) {
        if let indexPath = tableView.indexPath(for: cell) {
            // do Something
        }
    }
}
0
Changnam Hong

UIButton dans Uitableviewcell. Créer une méthode d'action par programme dans Swift 4.2

cell.btnlike.addTarget(self, action: #selector(buttonbtnlikePressed(_:event:)), for: .touchUpInside)


@objc func buttonbtnlikePressed(_ sender: Any, event: Any) {
        let point : CGPoint = (sender as AnyObject).convert(CGPoint.zero, to:tblPost)
        var indexPath =  self.tblPost!.indexPathForRow(at: point)
        if let btnlike = sender as? UIButton{
            if btnlike.isSelected{
                btnlike.isSelected = false
            }else{
                btnlike.isSelected = true
            }
        }
    }
0
Himanshu Moradiya