I am trying to use tap gesture recognizer to hide keyboard and drop down table view (which is created programatically in another view and is called when needed). The code I used in ViewDidLoad is
override func viewDidLoad() {
super.viewDidLoad()
tap = UITapGestureRecognizer(target: self, action:Selector("DismissKeyboard"))
view.addGestureRecognizer(tap!) }
and DismissKeyboard function is
func DismissKeyboard(){
view.endEditing(true)
subviewSchool.removeFromSuperview()
subviewPosition.removeFromSuperview()
}
Button action to call Dropdown Table View is
#IBAction func dropDownPosition(sender: AnyObject) {
var frameForDropDownViewPosition = CGRect()
var framePosition = selectPositionTextField.frame
frameForDropDownViewPosition.origin.x = framePosition.origin.x
frameForDropDownViewPosition.origin.y = studentCell.frame.origin.y + framePosition.origin.y + framePosition.size.height
frameForDropDownViewPosition.size.width = framePosition.size.width
frameForDropDownViewPosition.size.height = 300
subviewPosition = DropDownView(frame: frameForDropDownViewPosition)
subviewPosition.delegate = self
subviewPosition.indicator = "positionStudent"
subviewPosition.checkposition = schoolKeyId
subviewPosition.schoolInfoArr = schoolInfoArr
self.view.addSubview(subviewPosition)
}
But the problem is that Tab Gesture did work but I am Unable to Select the contain of Drop Down view (want to perform certain task when called did select row at index path) as tap gesture is not allowing me to do so.
How can I remove Tab Gesture from Drop Down Table View (or is there an alternative way?), as I can remove Tab Gesture from all view using
self.view.removeGestureRecognizer(tap!)
but not from specific view (which is not as plan), so that I can do my work as I desire. I am using Swift
Thank you
Add gestureDelegate:
UIGestureRecognizerDelegate
In ViewDidLoad set tap delegate:
tap.delegate = self
Then call this delegate
Swift 2
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
let p = touch.locationInView(view)
if CGRectContainsPoint(DropDownView.frame, p) {
return false
}
return true
}
Swift 4
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let p = touch.location(in: view)
if DropDownView.frame.contains(p) {
return false
}
return true
}
Drag and drop, the TapGestureRecognizer on to the ViewController in Main.Storyboard you want this
then go to documents outlet, select the TapGestureRecognizer, Control drag it to create IBOutlet in the ViewController.swift
create an outlet for TapGestureRecognizer, name it "tap"
#IBOutlet var tap: UITapGestureRecognizer!
add UIGestureRecognizerDelegate to the ViewController
UIGestureRecognizerDelegate
in viewDidLoad() or in the #IBAction of your interest
tap.delegate = self
Then call this delegate function
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
let p = touch.locationInView(view)
if CGRectContainsPoint(DropDownView.frame, p) {
return false
}
return true
}
if you are using the textFiled try by using textFiledDelegate Method for dismissing keyboard
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
If you want to recognise Tap gesture for multiple view. You need to add Tap Gesture SELECTOR for multiple views.
Please check below code hope it works for you.
- (void)viewDidLoad {
[super viewDidLoad];
//Added Tap Gesture to remove keyboard
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(processSingleTap:)];
[singleTapGesture setNumberOfTapsRequired:1];
[singleTapGesture setNumberOfTouchesRequired:1];
[self.tableViewObj addGestureRecognizer:singleTapGesture];
}
-(void)dismissKeyboard
{
[[[UIAlertView alloc]initWithTitle:#"Keyboard" message:#"Dismiss keyboard here..." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
-(void)processSingleTap:(UITapGestureRecognizer*)gesture
{
CGPoint pointInTableView = [gesture locationInView:self.tableViewObj];
NSIndexPath *selectedIndexPath = [self.tableViewObj indexPathForRowAtPoint:pointInTableView];
UITableViewCell *selectedCell = (UITableViewCell*)[self.tableViewObj cellForRowAtIndexPath:selectedIndexPath];
if(selectedCell){
[[[UIAlertView alloc]initWithTitle:#"Cell Selected" message:[NSString stringWithFormat:#"Cell Selected Index...%#",#(selectedIndexPath.row)] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
else
{
NSLog(#"Cell not selected tap of table view ...");
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"Cell %#",#(indexPath.row)];
return cell;
}
You can check if it was tapped inside UITableView.
Just have a look at this answer How get UITableView IndexPath from UITableView iphone?. It's a much better and a simple way.
Related
How do I add an action to a uiview that will run if a screen interaction (long press) moves to a uiview and then stays there for a select period of time.
EDIT: I have a drop down menu sort of system and a long press on the button reveals the menu. Then a user would slide down onto an option and then release the tap. I want to tell which menu item that happened on and act accordingly.
Add the below gesture to your UIView for long press functionality.
var longTap = UILongPressGestureRecognizer(target: self, action: #selector(self.longTouch))
longTap.numberOfTapsRequired = 0 // Set your own number here
longTap.minimumPressDuration = 1.0 //Set your duration here
longTap.delegate = self// Add the <UIGestureRecognizerDelegate> protocol
self.view.addGestureRecognizer(longTap)
Add the delegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Below is selector will be called
func longTouch(_ recognizer: UILongPressGestureRecognizer) {
if recognizer.state == .began {
print("longTouch UIGestureRecognizerStateBegan")
}
if recognizer.state == .ended {
print("longTouch UIGestureRecognizerStateEnded")
}
}
Objective C version
UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longTouch:)];
[longTap setNumberOfTapsRequired:0]; // Set your own number here
[longTap setMinimumPressDuration:1.0]; // Set your duration here
[longTap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol
[self.view addGestureRecognizer:longTap];
Delgate:-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Selector:-
- (void) longTouch: (UILongPressGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan)
{
NSLog(#"longTouch UIGestureRecognizerStateBegan");
}
if (recognizer.state == UIGestureRecognizerStateEnded)
{
NSLog(#"longTouch UIGestureRecognizerStateEnded");
}
}
I added a tap recognizer to a view:
UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector( onTap )];
[view addGestureRecognizer: tgr];
The problem is that taps on subviews of view trigger onTap. How do I prevent that?
Suppose your parentView has a subView. You implement the following UIGestureRecognizerDelegate method, if the touch is inside the bounds of subView, you return no.
tgr.delegate = self;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint locationInView = [touch locationInView:self.parentView];
if (CGRectContainsPoint(self.subView.frame, locationInView) ) {
return NO;
} else {
return YES;
}
}
Add subview to the background of the view, and attach tap gesture recogniser to the subview:
UIView* subview = [[UIView alloc] initWithFrame:view.bounds];
subview.backgroundColor = [UIColor clearColor];//or view.backgroundColor
[view addSubview:subview];
[view sendSubviewToBack:subview];
[subview addGestureRecognizer:tapRecognizer];
Swift 4.2 answer for an AlertView
Add the gesture recogniser and set the delegate:
let backgroundViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismiss))
backgroundViewTapGesture.delegate = self
self.backgroundView.addGestureRecognizer(backgroundViewTapGesture)
self.backgroundViewTapGesture = backgroundViewTapGesture
Then add the extension to handle the tap
extension AlertView: UIGestureRecognizerDelegate {
// Only handle this for the background tap gesture
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
guard gestureRecognizer == backgroundViewTapGesture, let backgroundView = gestureRecognizer.view, let alertView = self.alertContentView else {
return true
}
let touchLocation = touch.location(in: backgroundView)
return !alertView.frame.contains(touchLocation)
}
}
In Swift:
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let locationInView = touch.location(in: mainView)
if debugOptionsView.isHidden {
return true
}
return !debugOptionsView.frame.contains(locationInView)
}
How can I add a UITapGestureRecognizer to a UITextView but still have the touches getting through to the UITextView as normal?
Currently as soon as I add a custom gesture to my textView it blocks the tap for UITextView default actions like positioning the cursor.
var tapTerm:UITapGestureRecognizer = UITapGestureRecognizer()
override func viewDidLoad() {
tapTerm = UITapGestureRecognizer(target: self, action: "tapTextView:")
textView.addGestureRecognizer(tapTerm)
}
func tapTextView(sender:UITapGestureRecognizer) {
println("tapped term – but blocking the tap for textView :-/")
…
}
How can I process taps but keep any textView behaviour like cursor positioning as is?
To do that make your view controller adopt to UIGestureRecognizerDelegate and override should recognize simultaneously with gesture recognizer method like:
override func viewDidLoad() {
tapTerm = UITapGestureRecognizer(target: self, action: "tapTextView:")
tapTerm.delegate = self
textView.addGestureRecognizer(tapTerm)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
In case anyone came here looking for #Zell B.'s answer in Objective C, here's the code:
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(textViewTapped:)];
tap.delegate = self;
tap.numberOfTapsRequired = 1;
[self.textView addGestureRecognizer:tap];
}
- (void)textViewTapped:(UITapGestureRecognizer *)tap {
//DO SOMTHING
}
#pragma mark - Gesture recognizer delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
PS: Don't forget < UIGestureRecognizerDelegate >
Swift 4.2
The following steps allows me to escape a full-screen UITextView with a tap, whilst allowing to scroll the contents of the UITextView:
Disconnected the UIGestureRecognizer from the UITableView.
Made a CustomTextView: UITextView.
Added a 'sender' var to the particular UIViewController with the CustomTextView.
Trap for 'Touches Ended...'
Call for an excape function within the sender UIViewController.
class CustomTextView: UITextView {
var sender: DocViewController?
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let controller = sender {
controller.handleSwipeGesture()
}
}
}
I can either scroll the contents of the UITextView or merely tap to exit.
The 'sender' is set from the hosting UIViewController at creation.
Somehow I could not assign a delegate inside UIView so I came up with a button solution.
I insert a button that completely covers the textView and when tapped on textViewButton I do resign the button so textView shows.
#IBAction func textViewTapped(_ sender: UIButton) {
self.placeholderLabel.isHidden = true
self.textViewButton.resignFirstResponder()
}
I've been trying to dismiss the modal form sheet view on outside tap on iOS 8 with no luck,
I've tried this code
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapBehind:)];
[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];
- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window
//Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.
if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])
{
// Remove the recognizer first so it's view.window is valid.
[self.view.window removeGestureRecognizer:sender];
[self dismissModalViewControllerAnimated:YES];
}
}
}
But it doesn't detect outside view clicks, any suggestions ?
There are actually two problems in iOS 8. First, the gesture recognition does not begin.
I solved this by adding the UIGestureRecognizerDelegate protocol and implementing
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
return YES;
}
Also, don't forget to register the delegate with
recognizer.delegate = self;
Now the gesture recognizer should recognize gestures and the target method (handleTapBehind:) will be called.
Here comes the second problem in iOS 8: locationInView: doesn't seem to take the device orientation into account if nil is passed as a view. Instead, passing the root view works.
Here's my target code that seems to work for iOS 7.1 and 8.0:
if (sender.state == UIGestureRecognizerStateEnded) {
UIView *rootView = self.view.window.rootViewController.view;
CGPoint location = [sender locationInView:rootView];
if (![self.view pointInside:[self.view convertPoint:location fromView:rootView] withEvent:nil]) {
[self dismissViewControllerAnimated:YES completion:^{
[self.view.window removeGestureRecognizer:sender];
}];
}
}
In iOS 8, You can look at using the new UIPresentationController class. It gives you better control over the container around your custom view controller presentation (allowing you to correctly add a gesture recogniser of your own).
Here is a link to quite a simple tutorial as well: http://dativestudios.com/blog/2014/06/29/presentation-controllers/
Then add the dimming view tap-to-dismiss:
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[self.dimmingView addGestureRecognizer:singleFingerTap];
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
Swift 3.1 solution that works in both portrait and landscape.
class TapBehindModalViewController: UIViewController, UIGestureRecognizerDelegate {
private var tapOutsideRecognizer: UITapGestureRecognizer!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if(self.tapOutsideRecognizer == nil) {
self.tapOutsideRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapBehind))
self.tapOutsideRecognizer.numberOfTapsRequired = 1
self.tapOutsideRecognizer.cancelsTouchesInView = false
self.tapOutsideRecognizer.delegate = self
self.view.window?.addGestureRecognizer(self.tapOutsideRecognizer)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if(self.tapOutsideRecognizer != nil) {
self.view.window?.removeGestureRecognizer(self.tapOutsideRecognizer)
self.tapOutsideRecognizer = nil
}
}
func close(sender: AnyObject) {
self.dismiss(animated: true, completion: nil)
}
// MARK: - Gesture methods to dismiss this with tap outside
func handleTapBehind(sender: UITapGestureRecognizer) {
if (sender.state == UIGestureRecognizerState.ended) {
let location: CGPoint = sender.location(in: self.view)
if (!self.view.point(inside: location, with: nil)) {
self.view.window?.removeGestureRecognizer(sender)
self.close(sender: sender)
}
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
I would like to handle a long press on a UITableViewCell to print a "quick access menu".
Did someone already do this?
Particularly the gesture recognize on UITableView?
First add the long press gesture recognizer to the table view:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];
Then in the gesture handler:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self.myTableView];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
} else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSLog(#"long press on table view at row %ld", indexPath.row);
} else {
NSLog(#"gestureRecognizer.state = %ld", gestureRecognizer.state);
}
}
You have to be careful with this so that it doesn't interfere with the user's normal tapping of the cell and also note that handleLongPress may fire multiple times (this will be due to the gesture recognizer state changes).
I've used Anna-Karenina's answer, and it works almost great with a very serious bug.
If you're using sections, long-pressing the section title will give you a wrong result of pressing the first row on that section, I've added a fixed version below (including the filtering of dummy calls based on the gesture state, per Anna-Karenina suggestion).
- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint p = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
} else {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.isHighlighted) {
NSLog(#"long press on table view at section %d row %d", indexPath.section, indexPath.row);
}
}
}
}
Answer in Swift 5 (Continuation of Ricky's answer in Swift)
Add the UIGestureRecognizerDelegate to your ViewController
override func viewDidLoad() {
super.viewDidLoad()
//Long Press
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
longPressGesture.minimumPressDuration = 0.5
self.tableView.addGestureRecognizer(longPressGesture)
}
And the function:
#objc func handleLongPress(longPressGesture: UILongPressGestureRecognizer) {
let p = longPressGesture.location(in: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: p)
if indexPath == nil {
print("Long press on table view, not row.")
} else if longPressGesture.state == UIGestureRecognizer.State.began {
print("Long press on row, at \(indexPath!.row)")
}
}
Here are clarified instruction combining Dawn Song's answer and Marmor's answer.
Drag a long Press Gesture Recognizer and drop it into your Table Cell. It will jump to the bottom of the list on the left.
Then connect the gesture recognizer the same way you would connect a button.
Add the code from Marmor in the the action handler
- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
CGPoint p = [sender locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
} else {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.isHighlighted) {
NSLog(#"long press on table view at section %d row %d", indexPath.section, indexPath.row);
}
}
}
}
Looks to be more efficient to add the recognizer directly to the cell as shown here:
Tap&Hold for TableView Cells, Then and Now
(scroll to the example at the bottom)
Answer in Swift:
Add delegate UIGestureRecognizerDelegate to your UITableViewController.
Within UITableViewController:
override func viewDidLoad() {
super.viewDidLoad()
let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)
}
And the function:
func handleLongPress(longPressGesture:UILongPressGestureRecognizer) {
let p = longPressGesture.locationInView(self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(p)
if indexPath == nil {
print("Long press on table view, not row.")
}
else if (longPressGesture.state == UIGestureRecognizerState.Began) {
print("Long press on row, at \(indexPath!.row)")
}
}
I put together a little category on UITableView based on Anna Karenina's excellent answer.
Like this you'll have a convenient delegate method like you're used to when dealing with regular table views. Check it out:
// UITableView+LongPress.h
#import <UIKit/UIKit.h>
#protocol UITableViewDelegateLongPress;
#interface UITableView (LongPress) <UIGestureRecognizerDelegate>
#property(nonatomic,assign) id <UITableViewDelegateLongPress> delegate;
- (void)addLongPressRecognizer;
#end
#protocol UITableViewDelegateLongPress <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didRecognizeLongPressOnRowAtIndexPath:(NSIndexPath *)indexPath;
#end
// UITableView+LongPress.m
#import "UITableView+LongPress.h"
#implementation UITableView (LongPress)
#dynamic delegate;
- (void)addLongPressRecognizer {
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 1.2; //seconds
lpgr.delegate = self;
[self addGestureRecognizer:lpgr];
}
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self];
NSIndexPath *indexPath = [self indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
}
else {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// I am not sure why I need to cast here. But it seems to be alright.
[(id<UITableViewDelegateLongPress>)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath];
}
}
}
If you want to use this in a UITableViewController, you probably need to subclass and conform to the new protocol.
It works great for me, hope it helps others!
Swift 3 answer, using modern syntax, incorporating other answers, and eliminating unneeded code.
override func viewDidLoad() {
super.viewDidLoad()
let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(tablePressed))
tableView.addGestureRecognizer(recognizer)
}
#IBAction func tablePressed(_ recognizer: UILongPressGestureRecognizer) {
let point = recognizer.location(in: tableView)
guard recognizer.state == .began,
let indexPath = tableView.indexPathForRow(at: point),
let cell = tableView.cellForRow(at: indexPath),
cell.isHighlighted
else {
return
}
// TODO
}
Just add UILongPressGestureRecognizer to the given prototype cell in storyboard, then pull the gesture to the viewController's .m file to create an action method.
I made it as I said.
Use the UITouch timestamp property in touchesBegan to launch a timer or stop it when touchesEnded got fired