Reputation: 741
I want to implement a custom UITableViewCell class that is made up of subviews such as, labels, buttons, and images. These cells will display content fetched from the web using an API.
I do not want to implement the UITableView delegate method didSelectRowAtIndexPath
as this will make the entire cell selectable. Only the button in the cell should be able to trigger any action.
The button is connected from the storyboard to the custom UITableViewCell via IBOutlet. The addTarget(_:action:forControlEvents:)
method is called on the UIButton in cellForRowAtIndexPath
of the UITableViewController class.
The roadblock occurs when we want to detect the indexPath
of the selected cell in the Selector function of the button.
This is how the indexPath
for the selected cell can be detected in the Selector function
@IBAction func doSomething(sender: AnyObject) {
var location: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
var indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(location)!
println("The indexPath for Selected Cell is - \(indexPath.row)")
}
Although, this successfully gets me around the issue, my question is;
1) Have you found an alternate way of being able to use UIButtons to pass selected cell data in a custom UITableViewCell?
2) What would be the best practice, so far, in Swift to implement a similar scenario?
Upvotes: 1
Views: 972
Reputation: 154593
If your tableView only has one section, you can use the tag
property of the button to store the indexPath.row
.
In cellForRowAtIndexPath
, when you set the target-action for the button, set button.tag = indexPath.row
.
Then in your doSomething
routine:
@IBAction doSomething(sender: UIButton) {
println("This button is from row - \(sender.tag)")
}
Upvotes: 1
Reputation: 1336
One way would be to iterate over the superviews of the sender and see if a UITableViewCell can be found...
Let's say you created a generic UIView extension with a method that would check to see if any of its superview's was a UITableViewCell...
extension UIView {
func parentTableViewCell() -> UITableViewCell? {
var view = self
while let superview = view.superview {
if let cell = superview as? UITableViewCell {
return cell
} else {
view = superview
}
}
return nil
}
}
Then you could do the following...
if let cell = (sender as UIView).parentTableViewCell() {
let indexPath = tableView.indexPathForCell(cell)
println("The row for this cell is - \(indexPath.row)")
}
Another way would be to use the tag
property of a view by setting it to an Int and then check to see what the tag
of the sender was in the method.
i.e. In your tableView:cellForRowAtIndexPath:
method
cell.myButton.tag = indexPath.row
Then in your doSomething
method
let rowIndex = (sender as UIButton).tag
println("The row for this cell is - \(rowIndex)"
Upvotes: 2