Pressione e segure no UITableView

Eu gostaria de lidar com uma pressão longa em um UITableViewCell para imprimir um “menu de access rápido”. Alguém já fez isso?

Particularmente o gesto reconhece no UITableView ?

Primeiro adicione o reconhecedor de gestos de imprensa longa à exibição de tabela:

 UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; lpgr.minimumPressDuration = 2.0; //seconds lpgr.delegate = self; [self.myTableView addGestureRecognizer:lpgr]; [lpgr release]; 

Então, no manipulador de gestos:

 -(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); } } 

Você deve ter cuidado com isso para que não interfira com o toque normal do usuário na célula e também observe que o handleLongPress pode triggersr várias vezes (isso será devido às mudanças de estado do reconhecedor de gesto).

Eu usei a resposta de Anna-Karenina, e funciona quase muito bem com um bug muito sério.

Se você estiver usando seções, pressionando longamente o título da seção lhe dará um resultado errado de pressionar a primeira linha nessa seção, eu adicionei uma versão fixa abaixo (incluindo a filtragem de chamadas falsas com base no estado do gesto, por Sugestão de Anna-Karenina).

 - (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); } } } } 

Aqui estão instruções esclarecidas combinando a resposta de Dawn Song e a resposta de Marmor.

Arraste um longo Reconhecedor de gestos de imprensa e solte-o na sua célula de tabela. Irá para o final da lista à esquerda.

insira a descrição da imagem aqui

Em seguida, conecte o reconhecedor de gestos da mesma maneira que você conectaria um botão. insira a descrição da imagem aqui

Adicione o código do Marmor no manipulador de ações

 - (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); } } } 

}

Parece ser mais eficiente adicionar o reconhecedor diretamente à célula, conforme mostrado aqui:

Toque e segure para células TableView, depois e agora

(vá até o exemplo na parte inferior)

Resposta no Swift:

Adicione o delegado UIGestureRecognizerDelegate ao seu UITableViewController.

Dentro do 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) } 

E a 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)") } } 

Resposta no Swift 3.0 (continuação da resposta de Ricky no Swift)

Adicione o UIGestureRecognizerDelegate ao seu ViewController

  override func viewDidLoad() { super.viewDidLoad() //Long Press let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress)) longPressGesture.minimumPressDuration = 0.5 longPressGesture.delegate = self self.tableView.addGestureRecognizer(longPressGesture) } 

E a function:

 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 == UIGestureRecognizerState.began) { print("Long press on row, at \(indexPath!.row)") } } 

Eu coloquei uma pequena categoria no UITableView baseado na excelente resposta de Anna Karenina.

Assim, você terá um método delegado conveniente, como está acostumado ao lidar com as visualizações regulares de tabela. Confira:

 // UITableView+LongPress.h #import  @protocol UITableViewDelegateLongPress; @interface UITableView (LongPress)  @property(nonatomic,assign) id  delegate; - (void)addLongPressRecognizer; @end @protocol UITableViewDelegateLongPress  - (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)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath]; } } } 

Se você quiser usar isso em um UITableViewController, você provavelmente precisará criar uma subclass e estar em conformidade com o novo protocolo.

Funciona muito bem para mim, espero que ajude os outros!

Basta adicionar o UILongPressGestureRecognizer à célula protótipo fornecida no storyboard e, em seguida, puxar o gesto para o arquivo .m do viewController para criar um método de ação. Eu fiz isso como eu disse.

Resposta do Swift 3, usando a syntax moderna, incorporando outras respostas e eliminando o código desnecessário.

 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 } 

Use a propriedade de registro de data e hora UITouch em touchesBegan para iniciar um cronômetro ou interrompê-lo quando os toquesEnded forem acionados