Issue Detecting Button cellForRowAt
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
}
Solution 1:
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 : (() -> Void)? @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 pass the UITableViewCell
instance as parameter and get the index path from there
class ButtonCell: UITableViewCell {
var callback : ((UITableViewCell) -> Void)?
@IBAction func buttonPressed(_ sender : UIButton) {
callback?(self)
}
}
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 = { cell in
let actualIndexPath = tableView.indexPath(for: cell)!
print("Button pressed", actualIndexPath)
}
return cell
}
If even the section
can change, well, then protocol/delegate may be more efficient.