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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…