Как я могу обнаружить двойной щелчок по определенной ячейке в UITableView?

Как я могу обнаружить двойной щелчок по определенной ячейке в UITableView ?

т.е. я хочу выполнить одно действие, если пользователь сделал одно касание, а другой, если пользователь сделал двойной контакт? Мне также нужно знать путь указателя, в котором было сделано касание.

Как я могу достичь этой цели?

Благодарю.

Если вы не хотите создавать подclass UITableView , используйте таймер с табличным представлением didSelectRowAtIndex:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //checking for double taps here if(tapCount == 1 && tapTimer != nil && tappedRow == indexPath.row){ //double tap - Put your double tap code here [tapTimer invalidate]; [self setTapTimer:nil]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Double Tap" message:@"You double-tapped the row" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert show]; [alert release]; } else if(tapCount == 0){ //This is the first tap. If there is no tap till tapTimer is fired, it is a single tap tapCount = tapCount + 1; tappedRow = indexPath.row; [self setTapTimer:[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(tapTimerFired:) userInfo:nil repeats:NO]]; } else if(tappedRow != indexPath.row){ //tap on new row tapCount = 0; if(tapTimer != nil){ [tapTimer invalidate]; [self setTapTimer:nil]; } } } - (void)tapTimerFired:(NSTimer *)aTimer{ //timer fired, there was a single tap on indexPath.row = tappedRow if(tapTimer != nil){ tapCount = 0; tappedRow = -1; } } 

НТН

Переопределите в свой class UITableView этот метод

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if(((UITouch *)[touches anyObject]).tapCount == 2) { NSLog(@"DOUBLE TOUCH"); } [super touchesEnded:touches withEvent:event]; } 

В подclassе UITableView выполните следующие действия:

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch* touch in touches) { if (touch.tapCount == 2) { CGPoint where = [touch locationInView:self]; NSIndexPath* ip = [self indexPathForRowAtPoint:where]; NSLog(@"double clicked index path: %@", ip); // do something useful with index path 'ip' } } [super touchesEnded:touches withEvent:event]; } 

Сначала определите:

 int tapCount; NSIndexPath *tableSelection; 

как переменные уровня classа в файле .h и выполнять всю необходимую настройку. Затем…

 - (void)tableView(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { tableSelection = indexPath; tapCount++; switch (tapCount) { case 1: //single tap [self performSelector:@selector(singleTap) withObject: nil afterDelay: .4]; break; case 2: //double tap [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap) object:nil]; [self performSelector:@selector(doubleTap) withObject: nil]; break; default: break; } } #pragma mark - #pragma mark Table Tap/multiTap - (void)singleTap { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Single tap detected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; tapCount = 0; } - (void)doubleTap { NSUInteger row = [tableSelection row]; companyName = [self.suppliers objectAtIndex:row]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"DoubleTap" delegate:nil cancelButtonTitle:@"Yes" otherButtonTitles: nil]; [alert show]; tapCount = 0; } 
 if([touch tapCount] == 1) { [self performSelector:@selector(singleTapRecevied) withObject:self afterDelay:0.3]; } else if ([touch tapCount] == 2) { [TapEnableImageView cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTapRecevied) object:self]; } 

Используйте функцию performSelector для вызова селектора вместо использования таймера. Это решает проблему, упомянутую @ V1ru8.

Я решил реализовать его, переопределив UITableViewCell .

MyTableViewCell.h

 @interface MyTableViewCell : UITableViewCell @property (nonatomic, assign) int numberOfClicks; @end 

MyTableViewCell.m

 @implementation MyTableViewCell - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *aTouch = [touches anyObject]; self.numberOfClicks = [aTouch tapCount]; [super touchesEnded:touches withEvent:event]; } 

TableViewController.m

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { MyTableViewCell *myCell = (MyTableViewCell*) [self.tableView cellForRowAtIndexPath:indexPath]; NSLog(@"clicks:%d", myCell.numberOfClicks); if (myCell.numberOfClicks == 2) { NSLog(@"Double clicked"); } } 

Другой ответ

 int touches; - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { touches++; if(touches==2){ //your action } } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { touches=0; } 

Вероятно, вам нужно подclassифицировать UITableView и переопределить любые события касания ( touchesBegan:withEvent touchesEnded:withEvent и т. Д.). Осмотрите события, чтобы узнать, сколько их было затронуто, и выполняйте свое обычное поведение. Не забудьте обратиться к методам касания UITableView's , иначе вы не получите поведение по умолчанию.

Согласно @lostInTransit, я подготовил код в Swift

 var tapCount:Int = 0 var tapTimer:NSTimer? var tappedRow:Int? override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { //checking for double taps here if(tapCount == 1 && tapTimer != nil && tappedRow == indexPath.row){ //double tap - Put your double tap code here tapTimer?.invalidate() tapTimer = nil } else if(tapCount == 0){ //This is the first tap. If there is no tap till tapTimer is fired, it is a single tap tapCount = tapCount + 1; tappedRow = indexPath.row; tapTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "tapTimerFired:", userInfo: nil, repeats: false) } else if(tappedRow != indexPath.row){ //tap on new row tapCount = 0; if(tapTimer != nil){ tapTimer?.invalidate() tapTimer = nil } } } func tapTimerFired(aTimer:NSTimer){ //timer fired, there was a single tap on indexPath.row = tappedRow if(tapTimer != nil){ tapCount = 0; tappedRow = -1; } } 

Примечание: см. Комментарии ниже, чтобы увидеть, хотя, хотя это решение сработало для меня, это может быть не очень хорошая идея.

Альтернативой созданию подclassа UITableView или UITableViewCell (и использованию таймера) было бы просто расширить class UITableViewCell с категорией, например (используя ответ @ oxigen, в этом случае для ячейки вместо таблицы):

 @implementation UITableViewCell (DoubleTap) - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if(((UITouch *)[touches anyObject]).tapCount == 2) { NSLog(@"DOUBLE TOUCH"); } [super touchesEnded:touches withEvent:event]; } @end 

Таким образом вам не придется переименовывать существующие экземпляры UITableViewCell с новым именем classа (расширит все экземпляры classа).

Обратите внимание, что теперь super в этом случае (это категория) не относится к UITableView а к его супер, UITView . Но фактический вызов метода touchesEnded:withEvent: находится в UIResponder (из которых UITView и UITableViewCell являются подclassами), поэтому нет никакой разницы.

Вот мое полное решение:

CustomTableView.h

 // // CustomTableView.h // #import  @interface CustomTableView : UITableView // Nothing needed here @end 

CustomTableView.m

 // // CustomTableView.m // #import "CustomTableView.h" @implementation CustomTableView // // Touch event ended // - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // For each event received for (UITouch * touch in touches) { NSIndexPath * indexPath = [self indexPathForRowAtPoint: [touch locationInView:self] ]; // One tap happened if([touch tapCount] == 1) { // Call the single tap method after a delay [self performSelector: @selector(singleTapReceived:) withObject: indexPath afterDelay: 0.3]; } // Two taps happened else if ([touch tapCount] == 2) { // Cancel the delayed call to the single tap method [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(singleTapReceived:) object: indexPath ]; // Call the double tap method instead [self performSelector: @selector(doubleTapReceived:) withObject: indexPath ]; } } // Pass the event to super [super touchesEnded: touches withEvent: event]; } // // Single Tap // -(void) singleTapReceived:(NSIndexPath *) indexPath { NSLog(@"singleTapReceived - row: %ld",(long)indexPath.row); } // // Double Tap // -(void) doubleTapReceived:(NSIndexPath *) indexPath { NSLog(@"doubleTapReceived - row: %ld",(long)indexPath.row); } @end 

Улучшение реакции оксигена .

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if(touch.tapCount == 2) { CGPoint touchPoint = [touch locationInView:self]; NSIndexPath *touchIndex = [self indexPathForRowAtPoint:touchPoint]; if (touchIndex) { // Call some callback function and pass 'touchIndex'. } } [super touchesEnded:touches withEvent:event]; } 

Решение Swift 3 от ответов на сравнение. Не нужно никаких расширений, просто добавьте этот код.

 override func viewDidLoad() { viewDidLoad() let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(sender:))) doubleTapGestureRecognizer.numberOfTapsRequired = 2 tableView.addGestureRecognizer(doubleTapGestureRecognizer) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:))) tapGestureRecognizer.numberOfTapsRequired = 1 tapGestureRecognizer.require(toFail: doubleTapGestureRecognizer) tableView.addGestureRecognizer(tapGestureRecognizer) } func handleTapGesture(sender: UITapGestureRecognizer) { let touchPoint = sender.location(in: tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { print(indexPath) } } func handleDoubleTap(sender: UITapGestureRecognizer) { let touchPoint = sender.location(in: tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { print(indexPath) } } 

Это решение работает только для UICollectionView или ячейки UITableView.

Сначала объявите эти переменные

int number_of_clicks;

BOOL thread_started;

Затем поместите этот код в свой файл didSelectItemAtIndexPath

 ++number_of_clicks; if (!thread_started) { thread_started = YES; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC), dispatch_get_main_queue(),^{ if (number_of_clicks == 1) { ATLog(@"ONE"); }else if(number_of_clicks == 2){ ATLog(@"DOUBLE"); } number_of_clicks = 0; thread_started = NO; }); } 

0,25 – это отсрочка между двумя щелчками. Я думаю, что 0.25 идеально подходит для обнаружения этого типа щелчка. Теперь вы можете обнаружить только один клик и два клика отдельно. Удачи

  • Изменение размера текстового поля UISearchBar?
  • Продолжительность анимации строки UITableView и обратный вызов завершения
  • Длительное нажатие на UITableView
  • Трюки для улучшения производительности прокрутки iPhone UITableView?
  • Как узнать, когда UITableView завершил ReloadData?
  • Выберите несколько строк в UITableview
  • Добавить салфетки для удаления UITableViewCell
  • Изменение поведения прокрутки по умолчанию в заголовке раздела UITableView
  • Ленивые загрузки изображений в UITableViewCell
  • Как остановить прокрутку UITextView при входе в нее
  • Как определить конец загрузки UITableView
  • Давайте будем гением компьютера.