web-dev-qa-db-fra.com

Comment ajouter un bouton avec un événement click sur UITableViewCell dans Swift?

Dans ma page principale, j'ai créé un fichier xib pour UITableViewCell. Je charge la cellule à partir de ce fichier xib et tout fonctionne bien. 

À l'intérieur de la cellule, j'ai des étiquettes et des boutons. Je vise à changer l'étiquette en cliquant sur le bouton de la cellule.

Mon code aime ci-dessous

import UIKit


class SepetCell: UITableViewCell{

    @IBOutlet var barcode: UILabel!
    @IBOutlet var name: UILabel!
    @IBOutlet var fav: UIButton!
    @IBOutlet var strep: UIStepper!
    @IBOutlet var times: UILabel!



    @IBAction func favoriteClicked(sender: UIButton) {
        println(sender.tag)
        println(times.text)

        SepetViewController().favorite(sender.tag)



    }
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

Ceci est mes fichiers xib derrière des codes comme .Swift.

Les codes de la page principale aiment ci-dessous:

  import UIKit
import CoreData

class SepetViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {

  @
  IBOutlet
  var sepetTable: UITableView!
    var barcodes: [CART] = []

  let managedObjectContext = (UIApplication.sharedApplication().delegate as!AppDelegate).managedObjectContext

  override func viewWillAppear(animated: Bool) {
    if let moc = self.managedObjectContext {


      var nib = UINib(nibName: "SepetTableCell", bundle: nil)
      self.sepetTable.registerNib(nib, forCellReuseIdentifier: "productCell")
    }
    fetchLog()
    sepetTable.reloadData()
  }

  func fetchLog() {

    if let moc = self.managedObjectContext {
      barcodes = CART.getElements(moc);
    }
  }



  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) - > Int {
    return self.barcodes.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {


    let cell = tableView.dequeueReusableCellWithIdentifier("productCell") as ? SepetCell


    if cell == nil {
      println("cell nil")

    }



    let product: CART
    product = barcodes[indexPath.row]



    cell!.barcode ? .text = product.barcode
    cell!.name ? .text = product.name
    cell!.fav.tag = indexPath.row

    return cell!
  }

  func favorite(tag: Int) {



  }
}

Quand j'ai cliqué sur le bouton fav à l'intérieur de la cellule. Je voulais changer le libellé des temps en n'importe quoi, par exemple.

Lorsque j'ai cliqué sur le bouton fav, l'événement est passé à la fonction SepetCell.Swift favoriteClicked (expéditeur: UIButton). 

Donc, si j'essaie d'appeler: SepetViewController (). Favorite (sender.tag)

Il ira à l'intérieur du 

func favorite(tag: Int) {

      sepetTable.reloadData()

    }

mais sepetTable est nul lorsqu'il y est allé. Je pense que c’est parce que j’appelle cette fonction SepetViewController (). Favorite (sender.tag). Il crée d’abord la classe SepetViewController. Donc, parce que l'objet n'est pas réglé, il devient nul.

Comment puis-je atteindre ce sepetTable ou quel est le meilleur moyen de résoudre ce problème.

Merci.

10

Les méthodes courantes pour résoudre ce problème sont les fermetures et les délégués ... Si vous souhaitez utiliser des fermetures, vous feriez quelque chose comme ceci:

final class MyCell: UITableViewCell {
    var actionBlock: (() -> Void)? = nil

puis

    @IBAction func didTapButton(sender: UIButton) {
        actionBlock?()
    }

puis dans votre délégué tableview:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
    cell?.actionBlock = {
       //Do whatever you want to do when the button is tapped here
    }

Une alternative populaire consiste à utiliser le modèle de délégué:

    protocol MyCellDelegate: class {
        didTapButtonInCell(_ cell: MyCell)
    }

    final class MyCell: UITableViewCell {
        weak delegate: MyCellDelegate?

puis 

    @IBAction func didTapButton(sender: UIButton) {
        delegate?.didTapButtonInCell(self)
    }

.. Maintenant dans votre contrôleur de vue:

puis dans votre délégué tableview:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) - > UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("MyCellIdentifier") as? MyCell
    cell?.delegate = self

Et ajoutez la conformité au protocole comme ceci:

extension MyViewController: MyCellDelegate {
    didTapButtonInCell(_ cell: MyCell) {
       //Do whatever you want to do when the button is tapped here
    }
}

J'espère que cela t'aides!

44
raf

Tous les modèles ci-dessus sont bien . Mes deux cents, au cas où vous ajouteriez par code (par exemple, plusieurs cellules différentes, etc.) Il existe une solution simple FAR.

Comme les boutons permettent de spécifier une "cible" Vous pouvez passer directement le contrôleur ET l’action à la cellule/au bouton lors du réglage.

Dans le contrôleur:

let selector = #selector(self.myBtnAction)
setupCellWith(target: self, selector: selector)

...

dans une cellule personnalisée avec bouton:

final func setupCellWith(target: Any? selector: Selector){
       btn.addTarget(target, 
        action: selector,
       for: .touchUpInside)

}
0
ingconti