Swift - add gesture recognizer to object in table cell
Here's a quick Swift-translation of the linked post's solution, adding the swipe gesture recognizer to the UITableView and then determining which cell the swipe happened on:
class MyViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
var recognizer = UISwipeGestureRecognizer(target: self, action: "didSwipe")
self.tableView.addGestureRecognizer(recognizer)
}
func didSwipe(recognizer: UIGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Ended {
let swipeLocation = recognizer.locationInView(self.tableView)
if let swipedIndexPath = tableView.indexPathForRowAtPoint(swipeLocation) {
if let swipedCell = self.tableView.cellForRowAtIndexPath(swipedIndexPath) {
// Swipe happened. Do stuff!
}
}
}
}
}
Add Gesture Recognizer to specify object of cell in table
You should get the image view from the gesture. There is no need to use an instance variable for imgConfirm
. You also need to create a separate gesture recognizer for each image view. You can't reuse the same one over and over.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
// Configure the cell...
UIImageView *imgConfirm = (UIImageView *)[cell viewWithTag:107];
[imgConfirm setImage:[UIImage imageNamed:@"icon2"]];
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] inittWithTarget:self action:@selector(tapGestureTap:)];
// setup gesture as needed
[imgConfirm addGestureRecognizer:gesture];
return cell;
}
- (IBAction)tapGestureTap:(UITapGestureRecognizer *)sender {
UIImageView *imgConfirm = (UIImageView *)sender.view;
NSData* imgConfirmData1 = UIImagePNGRepresentation(imgConfirm.image);
NSData* imgConfirmData2 = UIImagePNGRepresentation([UIImage imageNamed:@"icon2"]);
if ([imgConfirmData1 isEqualToData:imgConfirmData2]) {
[imgConfirm setImage:[UIImage imageNamed:@"icon"]];
}
else{
[imgConfirm setImage:[UIImage imageNamed:@"icon2"]];
}
}
One important piece missing here is that if the user scrolls the table, the image will be reset. You need to add more code to keep track of the current state of each image so your cellForRowAtIndexPath:
sets the proper image.
How to add gesture to UITableViewCell?
To add gesture to UITableViewCell, you can follow the steps below:
First, add gesture recognizer to UITableView
tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self
Then, define the selector. Use recognizer.locationInView
to locate the cell you tap in tableView. And you can access the data in your dataSource by tapIndexPath
, which is the indexPath of the cell the user tapped.
func tapEdit(recognizer: UITapGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Ended {
let tapLocation = recognizer.locationInView(self.tableView)
if let tapIndexPath = self.tableView.indexPathForRowAtPoint(tapLocation) {
if let tappedCell = self.tableView.cellForRowAtIndexPath(tapIndexPath) as? MyTableViewCell {
//do what you want to cell here
}
}
}
}
It is possible to add gesture directly to TableView cell and access the datasource in viewController, You need to set up a delegate:
In your custom cell:
import UIKit
class MyTableViewCell: UITableViewCell {
var delegate: myTableDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:)))
addGestureRecognizer(tapGesture)
//tapGesture.delegate = ViewController()
}
func tapEdit(sender: UITapGestureRecognizer) {
delegate?.myTableDelegate()
}
}
protocol myTableDelegate {
func myTableDelegate()
}
In your viewController:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate, myTableDelegate {
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 35
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? MyTableViewCell
cell?.delegate = self
return cell!
}
func myTableDelegate() {
print("tapped")
//modify your datasource here
}
}
However, this method could cause problems, see UIGestureRecognizer and UITableViewCell issue. In this case, when the swipe gesture successes, the selector get called twice for some reason. I can't say the second method is a bad one as I haven't found any direct evidence yet, but after searching through Google, it seems like the first method is the standard way.
How can I add a UITapGestureRecognizer to a UILabel inside a table view cell?
EASY WAY:
You may also use a invisible button on the top of that label. So it will reduce your work of adding tapGesture for that label.
ALTERNATIVE WAY:
You should not create an IBOutlet for that UILabel
. When you do that,you will add a outlet in custom class implementation file. You cannot access in other file. So set a tag for that label in custom class IB
and write a code in cellForRowAtIndexPath:
method.
UPDATED:
In cellForRowAtIndexPath:
method,
for(UIView *view in cell.contentViews.subviews) {
if(view.tag == 1) {
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
[tap setNumberOfTapsRequired:1];
[view addGestureRecognizer:tap];
}
}
UIGestureRecognizer and UITableViewCell issue
Instead of adding the gesture recognizer to the cell directly, you can add it to the tableview in viewDidLoad
.
In the didSwipe
-Method you can determine the affected IndexPath and cell as follows:
-(void)didSwipe:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
CGPoint swipeLocation = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:swipeLocation];
UITableViewCell* swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
// ...
}
}
Related Topics
Swift - How to Open Specific View Controller When Push Notification Received
Today Extension View Flashes When Redrawing
iOS - Spritekit - How to Calculate the Distance Between Two Nodes
How to Detect User Uninstalled iOS App? I Need Push Serious Notification. I Don't Wanna Lose It
iOS Web App: Showing Content Only If the Application Is Standalone
Geofire Query on User Location
How to Encrypt and Decrypt a String(Plain Text) with Rsa Public Key in iOS, Swift
Avplayer Uitapgesturerecognizer Not Working
Make Uisearchcontroller Search Bar Automatically Active
iOS - Custom Table Cell Not Full Width of Uitableview
How to Record Actual Sound on the Simulator Using Mic
Xcode:How to Set App to Be iPhone Only
Is There a Custom Url Scheme for the Built-In Contacts App
Cannot Get My Location to Show Up in Google Maps in iOS 8
Why Don't My Views Show Up in Storyboards and Are Greyed Out in the Left Pane