-didSelectRowAtIndexPath: não sendo chamado


295

Estou escrevendo um aplicativo para iOS com uma visualização de tabela em uma visualização de guia. No meu UITableViewController, eu implementei -tableView:didSelectRowAtIndexPath:, mas quando seleciono uma linha em tempo de execução, o método não está sendo chamado. A visualização de tabela está sendo preenchida, portanto, eu sei que outros métodos tableView no meu controlador estão sendo chamados.

Alguém tem alguma idéia do que eu possa ter estragado para fazer isso acontecer?


79
Também você pode ter um GestureRecognizer no topo do UITableView que absorve a seleção .. (uma das possibilidades)
M.Othman

Tenha cuidado se a visualização da tabela estiver sendo preenchida, isso significa que o DataSource está bem definido. A seleção faz parte dos métodos de delegação. Talvez o DataSource esteja bem definido, mas não o Delegado!
Thomas Besnehard

1
Olá M.Othman, seu comentário é exatamente o que estava errado com meu próprio problema. Você sabe como obter o gestoRecognizer trabalhando 'com' o UITableView?
yhl 30/09

15
Percebo que, se eu tocar sem soltar, a torneira eventualmente chama -didSelectRowAtIndexPath. Eu descobri o chapéu, porque tenho um reconhecedor de gestos na tela e o gesto precisa falhar antes de receber o toque. Embora seja estranho, a animação de seleção de tabela não é afetada pelo reconhecedor de gestos.
Hlung

6
Eu tive o mesmo problema aqui e tive a oportunidade de saber que você não pode ter um gestoRecognizador no topo do UITableView. Obrigado M. Othman!
precisa saber é o seguinte

Respostas:


97

Parece que talvez a classe não seja a UITableViewDelegateda exibição de tabela, embora deva UITableViewControllerdefinir isso automaticamente.

Alguma chance de você redefinir o delegado para outra classe?


7
Descobri que, enquanto meu controlador era um UITableViewController, usei um widget UIViewController antigo simples no UI Builder. Isso não funciona. Quando excluí o widget UIViewController e soltei um UITableViewController em seu lugar, tudo funcionou.
Matt Pfefferle

1
Outro caso de fronteira para todos - eu liguei o delegado em código e esqueci que já havia ligado o delegado através do storyboard .... o último a definir é o vencedor.
Oliver Dungey

1
você pode mostrar como "redefinir um delegado para outra classe", por favor? Eu tenho esse mesmo problema e não consegue resolvê-lo
Alfro

1
myTableViewController.tableView.delegate = xxx
Hunter

534

Apenas no caso de alguém cometer o mesmo erro estúpido que eu:

Verifique se o nome do método que você espera ser didSelectacidentalmente pode ser obtido didDeselectde alguma forma. Demorou cerca de duas horas para eu descobrir ...


47
O mesmo problema aqui. É porque o XCode preenche automaticamente a opção Desmarcar antes do Selecionar.
user1021430

Da mesma forma, eu configurei allowSelection = false, que além de remover qualquer destaque de seleção, também impede que a célula seja pressionada!
djinne95

503

Outra coisa que pode levar ao problema não é o tipo de seleção selecionado:

Tipo de seleção UITableView

Deve ser Single Selectionpara seleção normal, não deve ser No Selection.

Para fazer isso programaticamente, faça:

tableView.allowsSelection = YES

4
Eu continuo me deparando com isso porque tenho cenas que estão sempre no modo de edição e esqueci de alterar o padrão de "Nenhuma seleção durante a edição".
Simétrica

3
Você pode adicionar essa linha no seu método -viewDidLoad do viewControlller NSParameterAssert (self.tableView.allowsSelection);
Nikolay Shubenkov

para aqueles que observaram tableView.rx.itemSelected.subscribe não funcionavam chamada de volta, este é o problema e correção acima obras
Dhilip

tão útil quando você assume o controle de alguma base de código e ele possui código usando botões com tags e não didSelectRow, com essa seleção desabilitada no storyboard #
Nitin Alabur

esse comportamento padrão da tableView?
Frostmourne

296

Outra possibilidade é que um UITapGestureRecognizer possa estar comendo os eventos, como foi o caso aqui: https://stackoverflow.com/a/9248827/214070

Não suspeitei dessa causa, porque as células da tabela ainda destacariam o azul como se as torneiras estivessem passando.


Este foi o meu problema! Muito obrigado!! Quero dizer, claramente funcionou antes, mas parou de funcionar após a implementação do UITapGestureRecognizer * tap = [[alocação do UITapGestureRecognizer] initWithTarget: self action: @selector (unlockKeyboard)]; [self.view addGestureRecognizer: toque];
coolcool1994

26
Eu tive o mesmo problema que você @ coolcool1994 acabou de implementar [tap setCancelsTouchesInView: NO]; e resolveu o problema.
Nizx

Obrigado, isso me ajuda. No meu caso didSelectRowAtIndexPath, não funciona apenas após excluir a célula commitEditingStyle. Então eu faço UITapGestureRecognizere tapAction:tenho indexPathde sender.view( [self.tableView indexPathForCell:sender.view]) e chamada[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon

1
Este também foi o meu problema .. adicione código para remover a tapgesture na tableview e funcionou como charme - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * Gestor = [[UITapGestureRecognizer ] iniciar]; speech.cancelsTouchesInView = NÃO; [self.tableView addGestureRecognizer: gesto]; }
Udaya Sri

6
Obrigado @nizx, em swift 4 tap.cancelsTouchesInView = false
Ariven Nadar

150

Todas as boas respostas, mas há mais uma a procurar ...

(Principalmente ao criar um UITableView programaticamente)

Verifique se o tableView pode responder à seleção definindo [tableView setAllowsSelection:YES];ou removendo qualquer linha que a defina NO.


9
Eu gostaria de acrescentar setAllowsSelectionDuringEditing:à lista (quando tableview está no modo de edição)
alex-i

Obrigado! No IB, tive que alterar o valor da seção "Seleção" para Single Selection.
Sasho 31/07

90

Se o problema surgir, UITapGestureRecognizervocê pode corrigir isso:

  • no Storyboard:

insira a descrição da imagem aqui

em código com Objective-C:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; 
[self.view addGestureRecognizer:tap];

[tap setCancelsTouchesInView:NO];

em código com Swift:

let tap = UITapGestureRecognizer(target: self, action:Selector("dismissKeyboard"))
view.addGestureRecognizer(tap)

tap.cancelsTouchesInView = false

67

Eu encontrei duas coisas nessas situações.

  1. Você pode ter se esquecido de implementar o protocolo UITableViewDelegate ou não há saída de delegação entre sua classe e sua exibição de tabela.

  2. Você pode ter um UIView em sua linha que é o primeiro a responder e retira seus cliques. Diga um UIButton ou algo semelhante.


5
Começou a acontecer no iOS 7, desativando a "Interação do usuário ativada" das visualizações no contentView, corrigiu isso.
Kof

1
@Kof acertou em cheio. Criar um UITableViewCell no construtor de interface do Xcode 5 cria-o com a interação do usuário ativada = YES. Xcode 5 ruim!
Jsd #

44

Eu tive o mesmo problema. E foi difícil de encontrar. Mas em algum lugar do meu código estava este:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    return nil;
}

Deve ser return indexPath, caso contrário, -tableView:didSelectRowAtIndexPath:não está sendo chamado.


2
para fizeram SelectRow No IndexPath assinatura correta é: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994

Para mim, ele não iria começar a chamar tableView: didSelectRowAtIndexPath até eu deletei willSelectRowAtIndexPath inteiramente
etayluz

38

Se você adicionou um gestoRecognizador na parte superior do UITableView, didSelectRowAtIndexPathnão será chamado.

Portanto, você precisa usar o método de delegação gestRecognizer para evitar o toque em uma exibição específica.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:YourTable]) {
        return NO;
    }
    return YES;
}

3
if ([touch.view isDescendantOfView:YourTable])
Sudheesh

29

Eu encontrei um problema em que, depois de meses sem olhar para o meu código, esqueci que implementei o método a seguir devido a alguns requisitos que não eram necessários

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath  *)indexPath{
    return NO;
}

Ele deve retornar SIM para uma linha para torná-la selecionada.


24

VOCÊ DEVE selecionar essas opções

insira a descrição da imagem aqui

mas se você não deseja UITableViewdestacar o clique, faça alterações nas UITableViewCellpropriedades.

Escolha a opção Nenhum para a seleção, como abaixo

insira a descrição da imagem aqui


20

Eu tinha colocado uma UITapGestureRecognizervisão na minha mesa para descartar o teclado que impedia didSelectRowAtIndexPath:de ser chamado. Espero que ajude alguém.



19

Eu tive o mesmo problema,

O motivo foi o uso de UITapGestureRecognizer. Eu queria que o teclado fosse descartado quando toquei em qualquer outro lugar. Percebi que isso substitui todas as ações de toque, por isso a didSelectRowAtIndexPathfunção não foi chamada.

Quando eu comento as linhas relacionadas UITapGestureRecognizer, ele funciona. Além disso, você pode verificar se a função UITapGestureRecognizer selectortocada é UITableViewCellou não.


14

No meu caso, didSelctRowAtIndexPath não chamando deve-se ao fato de eu ter selecionado nenhum na propriedade Selection do tableView, definido como a seleção única, resolvido o meu problema

insira a descrição da imagem aqui


11

Para o Xcode 6.4, Swift 1.2. A seleção "tag" foi alterada no IB. Não sei como e por quê. Configurá-lo para "Seleção única" tornou minhas células de exibição de tabela selecionáveis ​​novamente. insira a descrição da imagem aqui


10

Mesmo que outra resposta tenha sido aceita, adicionarei mais um possível problema e solução para as pessoas que observam esse problema:

Se você tiver a contagem automática de referência (ARC) ativada, poderá descobrir que, mesmo depois de atribuir seu controlador como delegado da exibição, as mensagens da exibição para o controlador não serão recebidas porque o ARC está excluindo o controlador. Aparentemente, o ponteiro delegado do UITableView não conta como referência para o ARC; portanto, se essa for a única referência a ele, o controlador será desalocado. Você pode verificar se isso está acontecendo ou não, implementando o método dealloc no controlador e definindo um ponto de interrupção ou chamada NSLog lá.

A solução é acompanhar o controlador com uma referência forte em outro lugar, até que você tenha certeza de que não precisará mais dele.


O controlador está sendo coletado de lixo enquanto sua visualização ainda é exibida? Isso pode realmente acontecer?
Drux

@Drux Yep! Quando isso aconteceu comigo, era quase a primeira versão do Obj-C com coleta de lixo usada no iOS e, honestamente, eles não fizeram um ótimo trabalho. Muitas referências foram explícitas ou implicitamente "fracas" que, na IMO, deveriam ter sido fortes. O que levou a esquisitices como a coleta de lixo de objetos em uso ativo pela camada de exibição. Não trabalho com o iOS há algum tempo, por isso não faço ideia se isso ainda acontece na versão mais recente.
Andrew Gorcester

Meu código tem um problema crescente de tamanho de memória, e eu o consertei e em algum outro lugar do código logo depois que esse didSelect não será chamado apenas na primeira vez. Não sei se isso justifica o problema ou não.
Amber K

10

Lembre-se de definir a fonte de dados e delegar no método viewDidLoad da seguinte maneira:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];

Eu estava chamando fonte de dados, mas não delegar ... obrigado!
Gmeister4

9

Meu problema não foi nenhum dos itens acima. E tão coxo. Mas pensei em listá-lo aqui, caso isso ajude alguém.

Eu tenho um tableViewControllerque é meu controlador "base" e, em seguida, crio subclasses desse controlador. Eu estava escrevendo todo o meu código na tableView:didSelectRowAtIndexPathrotina na classe "base". Esquecendo completamente que, por padrão, essa rotina também havia sido criada (embora sem código que fizesse alguma coisa) em todas as minhas subclasses também. Então, quando eu executei meu aplicativo, ele executou a versão da subclasse do código, não fez nada e me deixou triste. Então, é claro, depois que removi a rotina das subclasses, ele usou a rotina de classe mt "base" e estou no negócio.

Eu sei. Não ria Mas talvez isso poupe a alguém a hora que perdi ...


8

Dando meus 2 centavos nisso.

Eu tinha um UITableViewCell personalizado e havia um botão cobrindo a célula inteira; portanto, quando o toque aconteceu, o botão foi selecionado e não a célula.

Remova o botão ou, no meu caso, defino a Interação do usuário ativada como false no botão, dessa forma a célula foi a selecionada.


8

Se você ler isso, ainda assim não resolve o problema.

Eu tenho uma célula personalizada , onde a caixa de seleção " Interação do usuário ativada " foi desativada. Então, eu apenas ligo. Boa sorte.


7

Acabei de ter isso e, como aconteceu comigo no passado, não funcionou porque não prestei atenção ao preenchimento automático ao tentar adicionar o método e acabei implementando tableView:didDeselectRowAtIndexPath: em vez de tableView:didSelectRowAtIndexPath:.


7

Certifique-se de implementar tableView:didSelectRowAtIndexPathe nãotableView:didDeSelectRowAtIndexPath

Isso me pegou em mais de algumas ocasiões !!


5

Eu sei que é antigo e o problema foi resolvido, mas tive um problema semelhante, pensei que o problema estava com meu UITableViewCell personalizado, mas a solução era completamente diferente - eu reinicio o XCode :) e depois funciona ok! quase como o Windows :)


5

Se a visualização da tabela estiver no modo de edição (por exemplo [tableView setEditing:YES animated:NO];), é necessário definirtableView.allowsSelectionDuringEditing = YES;


4

Outro erro que você poderia ter cometido (como eu fiz): se você definir um segue na célula, didSelectRowAtIndexPathnão será chamado. Você deve definir seus segues no controlador de exibição.


4

Nenhuma dessas respostas funcionou para mim. Após cerca de uma hora, descobri algo muito traiçoeiro:

Eu tenho uma exibição de tabela dentro de uma célula de outra exibição de tabela. Decidi fazer uma visão anexa que contenha a visão interna da tabela, entre outras coisas. Chamei essa visualização de contentView e liguei-a no xib.

Acontece que o UITableViewCell já tem um contentView e faz coisas estranhas com ele. O problema foi resolvido quando eu renomeei a propriedade para mainContentView e reconecte a exibição a essa propriedade renomeada.


4

No meu caso, eu dinamicamente calcular a altura de os TableView's SuperViewno momento do carregamento. Devido a um erro de cálculo, o TableViewfoi posicionado fora do SuperView. A opção TableViewfoi selecionada, no entanto, toda a interação foi desativada (e didSelectRowAtIndexPathnunca foi chamada). Muito difícil de detectar, pois não há indicação visual de que o TableViewitem não seja "acessível".


4

No meu caso, o problema era que eu tinha uma UITableViewCellsubclasse e havia implementado esses dois métodos: touchesBegan:withEvent:& touchesEnded:withEventpara lidar com uma animação sofisticada ao toque. Mas eu tinha esquecido de adicionar o [super touchesBegan:touches withEvent:event];anúncio de método [super touchesEnded:touches withEvent:event];para também informar o pai da célula sobre o toque.

Então, alterar o código para o seguinte resolveu meu problema:

-(void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
    [super touchesBegan:touches withEvent:event];
    //blah blah blah
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    //rest of the code
}

1
Posso confirmar que isso causou o problema do OP para mim em particular
Josh Wolff

4

No meu caso, a solução foi alterar NÃO para SIM na função abaixo.

iOS 9 ou superior

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

Este também foi o meu problema. Eu tenho uma implementação tableView múltipla e esqueci de separar os dois tableViews neste método.
turingtested
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.