0

By clicking on the red area I get a comment id. But I also want to get the id if I click on the blue button. How can I do that? enter image description here

Right now I use this to detect a tap on a row. But tapping on button should run some other code.

extension FirstTabSecondViewComment: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        FirstTabSecondViewComment.subComment = table[indexPath.row].commentId ?? ""
        print(FirstTabSecondViewComment.subComment)
        self.performSegue(withIdentifier: "CommentDetail", sender: Any?.self)
    }
}
submariner
  • 308
  • 1
  • 5
  • 23
  • In `cellForRowAt` add a callback closure as described [here](https://stackoverflow.com/questions/58098923/how-to-get-index-path-on-click-of-button-from-uitableview-in-swift-5/58100909#58100909). In the closure call `performSegue`. Target/action and view-hierarchy-math is *unswifty*. – vadian Jun 06 '22 at 14:51

1 Answers1

0

After you have register your custom cell declare it in cellForRowAt and add target in button cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MyCell // your custom cell
    // add target in buoon cell
    cell.YourButtonCell.addTarget(self, action: #selector(submit(_:)), for: .touchUpInside)
    
    return cell
}

after that add submit func:

@objc fileprivate func submit(_ sender: UIButton) {
    var superview = sender.superview
    while let view = superview, !(view is UITableViewCell) {
        superview = view.superview
    }
    guard let cell = superview as? UITableViewCell else {
        print("button is not contained in a table view cell")
        return
    }
    guard let indexPath = tableView.indexPath(for: cell) else {
        print("failed to get index path for cell containing button")
        return
    }
    // We've got the index path for the cell that contains the button, now do something with it.
    print("button is in index \(indexPath.row)")
}

This is a full code example, copy and paste in a new project and run:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {


let tableView = UITableView()
let cellId = "cellId"

override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(tableView)
    tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(MyCell.self, forCellReuseIdentifier: cellId)
}

@objc fileprivate func submit(_ sender: UIButton) {
    var superview = sender.superview
    while let view = superview, !(view is UITableViewCell) {
        superview = view.superview
    }
    guard let cell = superview as? UITableViewCell else {
        print("button is not contained in a table view cell")
        return
    }
    guard let indexPath = tableView.indexPath(for: cell) else {
        print("failed to get index path for cell containing button")
        return
    }
    // We've got the index path for the cell that contains the button, now do something with it.
    print("button is in index \(indexPath.row)")
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 5
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 80
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! MyCell
    // add target in buoon cell
    cell.cancelButton.addTarget(self, action: #selector(submit(_:)), for: .touchUpInside)
    
    return cell
 }

}

class MyCell: UITableViewCell {

let cancelButton: UIButton = {
    let b = UIButton(type: .system)
    b.backgroundColor = .white
    b.setTitle("get Index", for: .normal)
    b.layer.cornerRadius = 10
    b.clipsToBounds = true
    b.titleLabel?.font = .systemFont(ofSize: 16, weight: .semibold)
    b.tintColor = .black
    b.translatesAutoresizingMaskIntoConstraints = false
    
    return b
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    contentView.backgroundColor = .darkGray
    
    contentView.addSubview(cancelButton)
    cancelButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
    cancelButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
    cancelButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    cancelButton.widthAnchor.constraint(equalToConstant: 300).isActive = true
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
 }
}
Fabio
  • 5,432
  • 4
  • 22
  • 24
  • Thank you for your answer. It shows me two issues. First of all it does not recognize my Button. It says 'Value of type 'TableViewCell' has no member 'newButton'' But I added the Button with Storyboard as ' @IBOutlet weak var newButton: UIButton!' And the second issue is it says 'Cannot infer contextual base in reference to member 'touchUpInside'' – submariner Jun 06 '22 at 14:22
  • @submariner I edited my answer with an example... Copy and paste in a new project and try.... The is a programmatically way... – Fabio Jun 06 '22 at 14:35