web-dev-qa-db-de.com

UITableViewCell Buttons mit Aktion

Hallo, ich habe eine benutzerdefinierte UITableViewCell mit drei Tasten, um eine Einkaufswagen-Funktion, Plus-, Minus- und Delete-Taste zu bedienen. Ich muss wissen, welche Zelle berührt wurde. 

Ich habe bereits versucht, die "Tag-Lösung" zu verwenden, die jedoch aufgrund des Lebenszyklus der Zellen nicht funktioniert. 

Kann mir bitte jemand helfen, eine Lösung zu finden?

Danke im Voraus 

6
jack87

Ich habe dies mithilfe einer Zellendelegierungsmethode in der Unterklasse von UITableViewCell gelöst.

Schneller Überblick:

1)Protokoll erstellen

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

2)nterklasse Ihr UITableViewCell (falls Sie dies nicht getan haben):

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

)Lassen Ihre Ansicht Controller entspricht dem oben implementierten Protokoll YourCellDelegate.

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

4)Stell einen Delegaten ein, nachdem die Zelle definiert wurde (zur Wiederverwendung).

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

5) Auf demselben Controller (auf dem sich Ihr UITableView-Delegat/Ihre UITableView-Datenquelle befindet) setzen Sie eine Methode aus dem YourCellDelegate-Protokoll.

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

Jetzt ist Ihre Lösung nicht mehr tag-/nummerabhängig. Sie können so viele Schaltflächen hinzufügen, wie Sie möchten, damit Sie eine Antwort per Stellvertreter erhalten, unabhängig davon, wie viele Schaltflächen Sie installieren möchten.

Diese protokolldelegierte Lösung wird in der iOS-Logik bevorzugt und kann für andere Elemente in Tabellenzellen wie UISwitch, UIStepper usw. verwendet werden.

50
pedrouan

Ich bin auf das gleiche Problem gestoßen, nachdem ich die IBOutlets privat gemacht hatte, wie von der Community allgemein vorgeschlagen.

Hier ist meine Lösung:

<In Ihrer Zellklasse>

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

class YourCell: UITableViewCell {

    weak var delegate: YourCellDelegate?

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

<In Ihrem 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

Swift 4.2

Anstelle von Delegaten können Sie auch Closures verwenden

1) In Ihrer UITableViewCell:

 class ExampleCell: UITableViewCell {
    //create your closure here  
         var buttonPressed : (() -> ()) = {}

        @IBAction func buttonAction(_ sender: UIButton) {
    //Call your closure here 
            buttonPressed()
        }
    }

2) In Ihrem ViewController

class ViewController:  UIViewController,  UITableViewDataSource, UITableViewDelegate {
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
   cell.buttonPressed = {
          //Code
           }
return cell 
  }
}
3
RimK

Sie können den ausgewählten Schaltflächenindex auch mithilfe der Hierarchie der tableViewCell-Ansicht abrufen.

Verwenden Sie folgende Schritte:

  1. fügen Sie der cellForRowAtIndexpath von tableview einen Selektor hinzu:

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

2 Rufen Sie indexPath mit folgender Methode ab: 

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. *

Es kann auch wie folgt durchgeführt werden. Nicht viel Codierung und Delegierung erforderlich. Einfach und leicht.

Fügen Sie folgenden Code in cellForItemAt für UICollectionView oder in cellForRowAt für UITableView ein 

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

Und deine Methode wird sein 

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

Das ist alles.

2
Abhishek Mitra

@pedrouan ist großartig, mit der Option tag der Schaltfläche. Wenn Sie die Schaltfläche auf tableViewCell setzen, ändern Sie in vielen Fällen tableView-Datenquellen (z. B. InsertRow, DeleteRow). 

Das Tag der Schaltfläche wird jedoch nicht aktualisiert, auch wenn eine neue Zelle inserted oder deleted ist. Daher ist es besser, die cell selbst als Parameter zu übergeben, anstatt die tag der Schaltfläche an den Parameter zu übergeben.

Hier ist mein Beispiel, um dies zu erreichen.

Ihre ExampleCell

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

class ExampleCell: UITableViewCell {

    weak var cellDelegate: ExampleCellDelegate?

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

Ihre 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 in Uitableviewcell. Programmgesteuerte Aktionsmethode in Swift 4.2 erstellen

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