Reputation: 1121
I have a UITableViewDataSource
with the following
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: OutletDetails.cellIdentifier) as! OutletDetails
cell.selectionStyle = .none
cell.isUserInteractionEnabled = true
cell.location = "Some location will be here"
let tap = UITapGestureRecognizer(target: self, action: #selector(locationClicked))
tap.cancelsTouchesInView = false
tap.numberOfTapsRequired = 1
cell.location.addGestureRecognizer(tap)
}
where cell.location
is a UILabel
object. What I'm trying to do here is to detect tap events on the UILabel
. I looked all over the Internet and everyone is suggesting this method, however, this code is not working in my case. The method locationClicked
is not being called at all. Can anyone tell me what's wrong with my code?
Edit
One more thing, is it a good idea to do it this way memory-wise? I mean if we have a long list, then many UIGestureRecognizer
objects will be generated for each cell. This is because the method will be called a lot while scrolling the items.
Upvotes: 0
Views: 1722
Reputation: 1121
Add tap gesture to the object and enable its user interaction. Yes you can take button as well.
//Adding tap gesture
let cellNameTapped = UITapGestureRecognizer(target: self, action: #selector(nameTapped))
nameLabel.isUserInteractionEnabled = true// UILabel made available for touch interaction
nameLabel.addGestureRecognizer(cellNameTapped) //gesture added
//Method called on touch of nameLabel
@objc func nameTapped(tapGestureRecognizer: UITapGestureRecognizer){
//print(tapGestureRecognizer.view)
}
Upvotes: 1
Reputation: 2916
Since you're dequeuing a cell, you will need to somehow get a reference to the UITapGestureRecognizer
and either remove it or reuse it. Otherwise every time you reuse a cell, you will be laying another recognizer onto the one that is already on the cell. If you're subclassing the UITableViewCell
you can just add the recognizer as a property.
However, using the code you posted I'm suggesting you use a UIButton
and add a tag so you can get a reference to it later. You can set the bounds of the button equal to the bounds of the label. Try something like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: OutletDetails.cellIdentifier) as! OutletDetails
cell.selectionStyle = .none
cell.isUserInteractionEnabled = true
cell.location = "Some location will be here"
// If we don't already have a button on our cell, create one and set the tag
if cell.viewWithTag(103) as? UIButton == nil {
let newButton = UIButton(frame: cell.location.bounds)
newButton.tag = 103
newButton.addTarget(target: self, action: #selector(locationClicked), for: .touchUpInside)
}
}
Upvotes: 0