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
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.
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
}
}
Vous pouvez également obtenir l'index de bouton sélectionné en utilisant la hiérarchie de la vue tableViewCell.
En utilisant les étapes suivantes:
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)
}
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.
@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
}
}
}
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
}
}
}