web-dev-qa-db-fra.com

Action UIButton dans la cellule de vue tableau

J'essaie d'exécuter une action pour un bouton enfoncé dans une cellule de la vue tableau. Le code suivant est dans ma classe de contrôleur de vue de table. 

Le bouton a été décrit comme "oui" dans une prise de ma classe UITableViewCell appelée "requestCell".

J'utilise Parse pour enregistrer des données et souhaite mettre à jour un objet lorsque le bouton est enfoncé. Mon tableau objectIds fonctionne bien, cell.yes.tag imprime également le numéro correct dans les journaux. Cependant, je ne peux pas obtenir ce numéro dans ma fonction "connecté" afin d'exécuter correctement ma requête. 

J'ai besoin d'un moyen d'obtenir le chemin indexPath.row de la cellule pour trouver le bon objectId. 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as requestsCell

    // Configure the cell...

    cell.name.text = requested[indexPath.row]

    imageFiles[indexPath.row].getDataInBackgroundWithBlock{
        (imageData: NSData!, error: NSError!) -> Void in

        if error == nil {

            let image = UIImage(data: imageData)

            cell.userImage.image = image
        }else{
            println("not working")
        }    
    }

    cell.yes.tag = indexPath.row
    cell.yes.targetForAction("connected", withSender: self)

    println(cell.yes.tag)

    return cell
}


func connected(sender: UIButton!) {

    var query = PFQuery(className:"Contacts")
    query.getObjectInBackgroundWithId(objectIDs[sender.tag]) {
        (gameScore: PFObject!, error: NSError!) -> Void in
        if error != nil {
            NSLog("%@", error)
        } else {
            gameScore["connected"] = "yes"
            gameScore.save()
        }
    }

}
34
Sammmmm

Vous devez ajouter une cible pour ce bouton.

myButton.addTarget(self, action: "connected:", forControlEvents: .TouchUpInside)

Et bien sûr, vous devez définir la balise de ce bouton puisque vous l'utilisez.

myButton.tag = indexPath.row

Vous pouvez y parvenir en sous-classant UITableViewCell. Utilisez-le dans le constructeur d’interface, déposez un bouton sur cette cellule, connectez-le via la sortie et le tour est joué.

EDIT: Pour obtenir le tag dans la fonction connectée:

func connected(sender: UIButton){
    let buttonTag = sender.tag
}

EDIT2:

Cette réponse a été fournie pour Swift 1.2, comme suggéré dans les commentaires, la syntaxe est légèrement différente pour Swift 2.2.

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

EDIT3:

Mis à jour pour Swift 3

myButton.addTarget(self, action: #selector(ClassName.FunctionName.buttonTapped), for: .touchUpInside)

EDIT4:

Mis à jour pour Swift 4

@objc func connected(sender: UIButton){
        let buttonTag = sender.tag
}
80
IxPaka

La réponse acceptée en utilisant button.tag comme support d’information sur lequel le bouton a été actionné est solide et largement acceptée, mais plutôt limitée puisqu'un tag peut uniquement contenir Ints.

Vous pouvez utiliser les capacités de fermeture impressionnantes de Swift pour obtenir une plus grande flexibilité et un code plus propre.

Je recommande cet article: Comment faire correctement des boutons dans les cellules de la vue tableau à l'aide de fermetures Swift de Jure Zove.

Appliqué à votre problème:

  1. Déclarez une variable pouvant contenir une fermeture dans votre tableview cell comme

    var buttonTappedAction : ((UITableViewCell) -> Void)?
    
  2. Ajoutez une action lorsque vous appuyez sur le bouton qui n’exécute que la fermeture. Vous l'avez fait par programme avec cell.yes.targetForAction("connected", withSender: self) mais je préférerais une sortie @IBAction :-)

    @IBAction func buttonTap(sender: AnyObject) {
       tapAction?(self)
    }
    
  3. Passez maintenant le contenu de func connected(sender: UIButton!) { ... } comme fermeture à cell.tapAction = {<closure content here...>}. Veuillez vous reporter à l'article pour une explication plus précise et n'oubliez pas de rompre les cycles de référence lors de la capture de variables de l'environnement.
34
Benedikt Reichert

Un moyen simple et facile de détecter un événement de bouton et d'effectuer une action

class youCell: UITableViewCell
{
    var yourobj : (() -> Void)? = nil

    //You can pass any kind data also.
   //var user: ((String?) -> Void)? = nil

     override func awakeFromNib()
        {
        super.awakeFromNib()
        }

 @IBAction func btnAction(sender: UIButton)
    {
        if let btnAction = self.yourobj
        {
            btnAction()
          //  user!("pass string")
        }
    }
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
        cell?.selectionStyle = UITableViewCellSelectionStyle.None

cell!. yourobj =
            {
                //Do whatever you want to do when the button is tapped here
                self.view.addSubview(self.someotherView)
        }

cell.user = { string in
            print(string)
        }

return cell

}
27
kalpesh

Nous pouvons créer une fermeture pour le bouton et l'utiliser dans cellForRowAtIndexPath

class ClosureSleeve {
  let closure: () -> ()

  init(attachTo: AnyObject, closure: @escaping () -> ()) {
    self.closure = closure
    objc_setAssociatedObject(attachTo, "[\(arc4random())]", self,.OBJC_ASSOCIATION_RETAIN)
}

@objc func invoke() {
   closure()
 }
}

extension UIControl {
func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
  let sleeve = ClosureSleeve(attachTo: self, closure: action)
 addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
 }
}

Et puis dans cellForRowAtIndexPath

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
    cell?.selectionStyle = UITableViewCell.SelectionStyle.none//Swift 4 style

      button.addAction {
       //Do whatever you want to do when the button is tapped here
        print("button pressed")
      }

    return cell
 }
3
levin varghese
class TableViewCell: UITableViewCell {
   @IBOutlet weak var oneButton: UIButton!
   @IBOutlet weak var twoButton: UIButton!
}


class TableViewController: UITableViewController {

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell

    cell.oneButton.addTarget(self, action: #selector(TableViewController.oneTapped(_:)), for: .touchUpInside)
    cell.twoButton.addTarget(self, action: #selector(TableViewController.twoTapped(_:)), for: .touchUpInside)

    return cell
}

func oneTapped(_ sender: Any?) {

    print("Tapped")
}

func twoTapped(_ sender: Any?) {

    print("Tapped")
   }
}
2
Biswajit Banik

En tant que Apple DOC

targetForAction: withSender: 
Renvoie l'objet cible auquel répond une action.

Vous ne pouvez pas utiliser cette méthode pour définir la cible pour UIButton.
Essayez addTarget (_: action: forControlEvents :) method

1
Huy Nghia

dans Swift 4

dans cellForRowAt indexPath:

 cell.prescriptionButton.addTarget(self, action: Selector("onClicked:"), for: .touchUpInside)

fonction exécutée après que l'utilisateur a appuyé sur le bouton:

@objc func onClicked(sender: UIButton){
        let tag = sender.tag


    }
0
m azizi