Acción UIButton en la celda de vista de tabla

Estoy intentando ejecutar una acción para presionar un botón dentro de una celda de vista de tabla. El siguiente código está en mi clase de controlador de vista de tabla.

El botón se ha descrito como “sí” en una salida de mi clase de UITableViewCell llamada requestsCell.

Estoy usando Parse para guardar datos y me gustaría actualizar un objeto cuando se presiona el botón. Mi matriz objectIds funciona bien, cell.yes.tag también imprime el número correcto en los registros, sin embargo, no puedo obtener ese número en mi función “conectada” para ejecutar mi consulta correctamente.

Necesito una forma de obtener el indexPath.row de la celda para encontrar el objectId adecuado.

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() } } } 

Necesita agregar un objective para ese botón.

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

Y, por supuesto, debe establecer la etiqueta de ese botón, ya que lo está usando.

 myButton.tag = indexPath.row 

Puede lograr esto subclasificando UITableViewCell. Úselo en el constructor de interfaz, suelte un botón en esa celda, conéctelo a través de la toma de stream y listo.

EDITAR: Para obtener la etiqueta en la función conectada:

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

EDIT2:

Esta respuesta se proporcionó para swift 1.2, como se sugiere en los comentarios, la syntax es un poco diferente para swift 2.2.

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

EDIT3:

Actualizado para Swift 3

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

EDIT4:

Actualizado para Swift 4

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

La respuesta aceptada utilizando button.tag como portador de información cuyo botón se ha pulsado realmente es sólida y ampliamente aceptada, pero bastante limitada, ya que una etiqueta solo puede contener Int . S.

Puede utilizar las increíbles capacidades de cierre de Swift para tener una mayor flexibilidad y un código más limpio.

Recomiendo este artículo: Cómo hacer correctamente los botones en las celdas de la vista de tabla utilizando cierres Swift de Jure Zove.

Aplicado a tu problema:

  1. Declare una variable que puede contener un cierre en su celda tableview como

     var buttonTappedAction : ((UITableViewCell) -> Void)? 
  2. Agregue una acción cuando se presione el botón que solo ejecuta el cierre. Lo hiciste programáticamente con cell.yes.targetForAction("connected", withSender: self) pero preferiría una salida de @IBAction 🙂

     @IBAction func buttonTap(sender: AnyObject) { tapAction?(self) } 
  3. Ahora pase el contenido de func connected(sender: UIButton!) { ... } como cierre de cell.tapAction = {} . Consulte el artículo para obtener una explicación más precisa y no olvide interrumpir los ciclos de referencia al capturar variables del entorno.

Una forma simple y fácil de detectar eventos de botones y realizar alguna acción

 class youCell: UITableViewCell { var yourobj : (() -> Void)? = nil override func awakeFromNib() { super.awakeFromNib() } @IBAction func btnAction(sender: UIButton) { if let btnAction = self.yourobj { btnAction() } } } 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) } return cell } 

Podemos crear un cierre para el botón y usarlo en 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) } } 

Y luego en cellForRowAtIndexPath

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell cell?.selectionStyle = UITableViewCellSelectionStyle.None button.addAction { //Do whatever you want to do when the button is tapped here print("button pressed") } return cell } 

Como Apple DOC

targetForAction: withSender:
Devuelve el objeto de destino que responde a una acción.

No puede usar ese método para establecer el destino para UIButton .
Pruebe el método addTarget (_: action: forControlEvents 🙂