Issue Detecting Button cellForRowAt

2020-01-24 03:08发布

I need to detect if the button has been clicked in the UITableViewController

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

 let LikesBtn = cell.viewWithTag(7) as! UIButton

}

3条回答
男人必须洒脱
2楼-- · 2020-01-24 03:46

Here is what I use:

First initialize the button as an Outlet and its action on your TableViewCell

class MainViewCell: UITableViewCell {

@IBOutlet weak var testButton: UIButton!

@IBAction func testBClicked(_ sender: UIButton) {

    let tag = sender.tag //with this you can get which button was clicked 

}



}

Then in you Main Controller in the cellForRow function just initialize the tag of the button like this:

class MainController: UIViewController, UITableViewDelegate, UITableViewDataSource, {

     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MainViewCell


        cell.testButton.tag = indexPath.row        

        return cell
    }

}
查看更多
放荡不羁爱自由
3楼-- · 2020-01-24 03:50

First step: Make Subclass for your custom UITableViewCell, also register protocol.

Something like this:

protocol MyTableViewCellDelegate: class {
    func onButtonPressed(_ sender: UIButton, indexPath: IndexPath)
}

class MyTableViewCell: UITableViewCell {

    @IBOutlet var cellButton: UIButton!

    var cellIndexPath: IndexPath!
    weak var delegate: MyTableViewCellDelegate!


    override func awakeFromNib() {
        super.awakeFromNib()

        cellButton.addTarget(self, action: #selector(self.onButton(_:)), for: .touchUpInside)
    }

    func onButton(_ sender: UIButton) {
        delegate.onButtonPressed(sender, indexPath: cellIndexPath)
    }

}

In your TableViewController, make sure it conform to your just created protocol "MyTableViewCellDelegate".

Look at the code below for better understanding.

class MyTableViewController: UITableViewController, MyTableViewCellDelegate {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as? MyTableViewCell {

            cell.cellIndexPath = indexPath
            cell.delegate = self

            return cell
        } else {
            print("Something wrong. Check your cell idetifier or cell subclass")
            return UITableViewCell()
        }
    }

    func onButtonPressed(_ sender: UIButton, indexPath: IndexPath) {
        print("DID PRESSED BUTTON WITH TAG = \(sender.tag) AT INDEX PATH = \(indexPath)")
    }
}
查看更多
够拽才男人
4楼-- · 2020-01-24 04:01

The easiest and most efficient way in Swift is a callback closure.

  • Subclass UITableViewCell, the viewWithTag way to identify UI elements is outdated.
  • Set the class of the custom cell to the name of the subclass and set the identifier to ButtonCellIdentifier in Interface Builder.

  • Add a callback property.

  • Add an action and connect the button to the action.

    class ButtonCell: UITableViewCell {
    
        var callback : (()->())?
    
        @IBAction func buttonPressed(_ sender : UIButton) {
           callback?()
        }
    }
    
  • In cellForRow assign the callback to the custom cell.

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCellIdentifier", for: indexPath) as! ButtonCell
         cell.callback = {
             print("Button pressed", indexPath)  
         }
         return cell
      }
    
  • When the button is pressed the callback is called. The index path is captured.

Edit

There is a caveat if cells can be added or removed. In this case update the index path by getting the current index from the data source array

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCellIdentifier", for: indexPath) as! ButtonCell
     let item = dataSourceArray[indexPath.row]
     // do something with item
     cell.callback = {
         let actualIndexPath = IndexPath(row: dataSourceArray.index(of: item)!, section: indexPath.section)
         print("Button pressed", actualIndexPath)  
     }
     return cell
  }

If even the section can change, well, then protocol/delegate may be more efficient.

查看更多
登录 后发表回答