-didSelectRowAtIndexPath: no se llama

295

Estoy escribiendo una aplicación de iOS con una vista de tabla dentro de una vista de pestaña. En mi UITableViewController, implementé -tableView:didSelectRowAtIndexPath:, pero cuando selecciono una fila en tiempo de ejecución, no se llama al método. Sin embargo, la vista de tabla se está completando, por lo que sé que se están llamando a otros métodos tableView en mi controlador.

¿Alguien tiene alguna idea de lo que he jodido para que esto suceda?

Matt Pfefferle
fuente
79
también puede tener un gesto Reconocimiento en la parte superior de UITableView que absorbe la selección ... (una de las posibilidades)
M.Othman
Tenga cuidado si la vista de tabla se está completando, significa que DataSource está bien configurado. La selección es parte de los métodos Delegado. ¡Quizás el DataSource esté bien configurado pero no el Delegado!
Thomas Besnehard
1
Hola M.Othman, su comentario es exactamente lo que estaba mal con mi propio problema. ¿Sabes cómo hacer que GestorReconocidor funcione 'con' el UITableView?
yhl
15
Noto que si toco y mantengo presionado, el toque finalmente llama -didSelectRowAtIndexPath. Descubrí los sombreros porque tengo un reconocedor de gestos de toque en la vista de la mesa y el gesto tiene que fallar primero antes de recibir el toque. Aunque es extraño, la animación de selección de tabla no se ve afectada por el reconocedor de gestos.
Hlung
66
Tuve el mismo problema aquí y tuve la afortunada oportunidad de aprender que no se puede tener un gesto Reconocidor encima de UITableView. Gracias M. Othman!
vnchopra

Respuestas:

97

Parece que tal vez la clase no es UITableViewDelegatepara esa vista de tabla, aunque UITableViewControllerse supone que establece eso automáticamente.

¿Hay alguna posibilidad de restablecer el delegado a alguna otra clase?

Hunter
fuente
77
Descubrí que, si bien mi controlador era un UITableViewController, utilicé un viejo widget UIViewController en UI Builder. Eso no funciona Cuando eliminé el widget UIViewController y coloqué un UITableViewController en su lugar, todo funcionó.
Matt Pfefferle
1
Otro caso límite para todos: conecté el delegado en código y olvidé que había conectado previamente al delegado a través del guión gráfico ... el último en configurarlo gana.
Oliver Dungey
1
¿puede mostrar cómo "restablecer un delegado a otra clase" por favor? Tengo este mismo problema y no puedo resolverlo
Alfro
1
myTableViewController.tableView.delegate = xxx
Hunter
534

Por si alguien cometió el mismo error estúpido que yo:

Verifique si el nombre del método de lo que espera ser didSelectpuede ser obtenido accidentalmente didDeselectde alguna manera. Me llevó unas dos horas descubrirlo ...

revs Dschee
fuente
47
Mismo problema aquí. Es porque XCode completa automáticamente la Deselección antes de Seleccionar.
user1021430
Del mismo modo, configuré allowSelection = false, que además de eliminar cualquier selección resaltada, ¡también evita que se presione la celda!
djinne95
503

Otra cosa que podría conducir al problema no es el tipo de selección seleccionado:

Tipo de selección UITableView

Debería ser Single Selectionpara la selección normal, no debería ser No Selection.

Para hacer esto mediante programación, haga:

tableView.allowsSelection = YES
Dennis Krut
fuente
44
Me encuentro con esto porque tengo escenas que siempre están en modo de edición y me olvido de cambiar el valor predeterminado de "Sin selección durante la edición".
Simétrico
3
Puede agregar esta línea en su método -viewDidLoad de viewControlller NSParameterAssert (self.tableView.allowsSelection);
Nikolay Shubenkov
para aquellos que observaron que tableView.rx.itemSelected.subscribe no devolvió la llamada, este es el problema y la solución anterior funciona
Dhilip
es muy útil cuando se hace cargo de una base de código y tiene código usando botones con etiquetas y no hizo SelectRow, con esta selección deshabilitada en el guión gráfico 🙄
Nitin Alabur
¿Es este comportamiento predeterminado de tableView?
Frostmourne
296

Otra posibilidad es que un UITapGestureRecognizer podría estar comiendo los eventos, como fue el caso aquí: https://stackoverflow.com/a/9248827/214070

No sospeché esta causa, porque las celdas de la tabla aún se resaltarían en azul como si los grifos estuvieran llegando.

revs pan de bicho
fuente
Este fue mi problema! ¡¡Muchas gracias!! Quiero decir que claramente funcionó antes, pero dejó de funcionar después de implementar UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector (dispatsKeyboard)]; [self.view addGestureRecognizer: toque];
coolcool1994
26
Tuve el mismo problema que usted @ coolcool1994 acaba de implementar [toque setCancelsTouchesInView: NO]; y resolvió el problema.
nizx
Gracias me ayuda. En mi caso didSelectRowAtIndexPath, no funciona solo después de eliminar la celda commitEditingStyle. Entonces hago UITapGestureRecognizery tapAction:tengo indexPathde sender.view( [self.tableView indexPathForCell:sender.view]) y la llamada[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon
1
Este también fue mi problema ... agregue código para eliminar la tapgestura en tableview y funcionó como encanto - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * gest = = [UITapGestureRecognizer alloc ] en eso]; gest.cancelsTouchesInView = NO; [self.tableView addGestureRecognizer: gesto]; }
Udaya Sri
66
Gracias @nizx, en rápido 4 tap.cancelsTouchesInView = false
Ariven Nadar
150

Todas buenas respuestas, pero hay una más a tener en cuenta ...

(Particularmente cuando se crea un UITableView programáticamente)

Asegúrese de que tableView puede responder a la selección configurando [tableView setAllowsSelection:YES];o eliminando cualquier línea que lo configure NO.

Old McStopher
fuente
99
Añadiría setAllowsSelectionDuringEditing:a la lista (cuando tableview está en modo de edición)
alex-i
¡Gracias! En IB tuve que cambiar en el valor de la sección "Selección" a Single Selection.
Sasho
90

Si surge el problema con UITapGestureRecognizerusted, puede solucionar esto:

  • en Storyboard:

ingrese la descripción de la imagen aquí

en código con Objective-C:

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

[tap setCancelsTouchesInView:NO];

en código con Swift:

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

tap.cancelsTouchesInView = false
Bartłomiej Semańczyk
fuente
67

Me he encontrado con dos cosas en estas situaciones.

  1. Es posible que haya olvidado implementar el protocolo UITableViewDelegate, o no hay una salida de delegación entre su clase y su vista de tabla.

  2. Es posible que tenga una UIView dentro de su fila que es el primero en responder y le quita sus clics. Diga un UIButton o algo similar.

gilm
fuente
55
Comenzó a suceder en iOS 7, deshabilitando "La interacción del usuario habilitada" de las vistas dentro de contentView solucionó esto.
Kof
1
@Kof lo clavó. Crear un UITableViewCell en el generador de interfaces de Xcode 5 lo crea con la interacción del usuario habilitada = SÍ. ¡Mal Xcode 5!
jsd
44

Yo he tenido el mismo problema. Y fue difícil de encontrar. Pero en algún lugar de mi código fue esto:

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

Debe ser return indexPath, de lo contrario -tableView:didSelectRowAtIndexPath:no se llama.

JackPearse
fuente
2
para did SelectRow At IndexPath la firma correcta es: - (nulo) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994
Para mí, no comenzaría a llamar a tableView: didSelectRowAtIndexPath hasta que eliminé willSelectRowAtIndexPath por completo
etayluz
38

Si agregó un gesto Reconocimiento encima de UITableView, didSelectRowAtIndexPathno se le llamará.

Por lo tanto, debe usar el método de delegado de gestorReconocidor para evitar tocar en una vista particular.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:YourTable]) {
        return NO;
    }
    return YES;
}
Vinu David Jose
fuente
3
if ([touch.view isDescendantOfView:YourTable])
Sudheesh
29

Me encontré con un problema en el que después de meses de no mirar mi código, olvidé que implementé el siguiente método debido a algunos requisitos que no eran necesarios.

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

Debería devolver YES para una fila para que se seleccione.

cpt.neverm1nd
fuente
24

DEBE seleccionar estas opciones

ingrese la descripción de la imagen aquí

pero si desea que UITableViewno se resalte al hacer clic, debe realizar cambios en las UITableViewCellpropiedades.

Elija la opción Ninguno para la selección como se muestra a continuación

ingrese la descripción de la imagen aquí

Mohsin Qureshi
fuente
20

Había puesto una UITapGestureRecognizervista de mi mesa para descartar el teclado que impedía didSelectRowAtIndexPath:que me llamaran. Espero que ayude a alguien.

Groot
fuente
19

Yo tuve el mismo problema,

La razón estaba usando UITapGestureRecognizer. Quería descartar el teclado cuando tocaba en cualquier otro lugar. Me di cuenta de que esto anula todas las acciones de tap, es por eso didSelectRowAtIndexPathque no se llamó a la función.

Cuando comento las filas relacionadas UITapGestureRecognizer, funciona. Además, puede verificar la función de UITapGestureRecognizer selectorsi el golpeado es UITableViewCello no.

Jeyhun Karimov
fuente
14

En mi caso, didSelctRowAtIndexPath no llama debido a que no he seleccionado ninguno en la propiedad Selection de tableView, establecer en selección única resolvió mi problema

ingrese la descripción de la imagen aquí

Naveed Ahmad
fuente
11

Para Xcode 6.4, Swift 1.2. La selección "etiqueta" había cambiado en IB. No sé cómo y por qué. Establecerlo en "Selección única" hizo que mis celdas de vista de tabla fueran seleccionables nuevamente. ingrese la descripción de la imagen aquí

MB_iOSDeveloper
fuente
10

Aunque se ha aceptado otra respuesta, agregaré un posible problema y una solución más para las personas que observan este problema:

Si tiene activado el conteo automático de referencias (ARC), puede encontrar que incluso después de asignar su controlador como delegado de la vista, los mensajes de la vista al controlador no se reciben porque ARC está eliminando el controlador. Aparentemente, el puntero de delegado de UITableView no cuenta como una referencia para el ARC, por lo que si esa es la única referencia, el controlador será desasignado. Puede verificar si esto está sucediendo o no implementando el método dealloc en el controlador y estableciendo un punto de interrupción o una llamada NSLog allí.

La solución es hacer un seguimiento del controlador con una referencia fuerte en otro lugar, hasta que esté seguro de que ya no lo necesitará.

Andrew Gorcester
fuente
¿El controlador se está recolectando basura mientras su vista todavía se muestra? ¿Puede esto realmente suceder?
Drux
@Drux ¡Sí! Cuando esto me sucedió, era casi la primera versión de Obj-C con recolección de basura utilizada en iOS y, sinceramente, no hicieron un gran trabajo. Muchas referencias eran explícita o implícitamente "débiles" que, en mi opinión, deberían haber sido fuertes. Lo que condujo a rarezas como la recolección de basura de objetos en uso activo por la capa de visualización. No he hecho el trabajo de iOS en un tiempo, así que no tengo idea de si esto todavía sucede en la última versión.
Andrew Gorcester
Mi código tiene un problema de tamaño de memoria cada vez mayor y lo arreglé un poco y en algún otro lugar del código justo después de que esto no se llamara a SelectSelect solo la primera vez. No sé si esto justifica el problema o no.
Amber K
10

Recuerde configurar el origen de datos y delegar en el método viewDidLoad de la siguiente manera:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];
Carlos
fuente
Estaba llamando a fuente de datos pero no delegado ... ¡gracias!
Gmeister4
9

Mi problema no fue ninguno de los anteriores. Y tan cojo. Pero pensé en enumerarlo aquí en caso de que ayude a alguien.

Tengo un tableViewControllerque es mi controlador "base" y luego creo subclases de este controlador. Estaba escribiendo todo mi código en la tableView:didSelectRowAtIndexPathrutina en la clase "base". Olvidando completamente que, por defecto, esta rutina también se había creado (aunque sin código que hiciera nada) en todas mis subclases. Entonces, cuando ejecuté mi aplicación, ejecutó la versión de subclase del código, no hizo nada y me puso triste. Entonces, por supuesto, una vez que eliminé la rutina de las subclases, usé la rutina de clase mt "base" y estoy en el negocio.

Lo sé. No te rías Pero tal vez esto le ahorrará a alguien la hora que perdí ...

Steve
fuente
8

Dando mis 2 centavos en esto.

Tenía un UITableViewCell personalizado y había un botón que cubría toda la celda, por lo que cuando se tocó, se seleccionó el botón y no la celda.

Quite el botón o, en mi caso, configuré la habilitación de la interacción del usuario en falso en el botón, de esa manera la celda fue la seleccionada.

gmogames
fuente
8

Si lees esto, todavía no resuelve el problema.

Tengo una celda personalizada , donde la casilla de verificación " Interacción del usuario habilitada " estaba deshabilitada. Entonces, solo lo enciendo. Buena suerte.

HotJard
fuente
7

Acabo de tener esto y, como me ha sucedido en el pasado, no funcionó porque no presté atención al autocompletado al intentar agregar el método y en realidad terminé implementando tableView:didDeselectRowAtIndexPath: en lugar de tableView:didSelectRowAtIndexPath:.

usuario486646
fuente
7

Asegúrese de implementar tableView:didSelectRowAtIndexPathy notableView:didDeSelectRowAtIndexPath

¡Esto me ha conseguido en más de unas pocas ocasiones!

SleepsOnNewspapers
fuente
5

Sé que es viejo y el problema se resolvió, pero tenía un problema similar, pensé que el problema estaba con mi UITableViewCell personalizado, pero la solución era completamente diferente: reinicio XCode :) y luego funciona bien. casi como Windows :)

Lukasz
fuente
5

Si su vista de tabla está en modo de edición (p. Ej. [tableView setEditing:YES animated:NO];), Debe configurartableView.allowsSelectionDuringEditing = YES;

Yvetterowe
fuente
4

Otro error que podría haber cometido (como lo hice): si establece un segue en la celda, didSelectRowAtIndexPathno se llama. En su lugar, debe establecer sus valores en el controlador de vista.

juanignaciosl
fuente
4

Ninguna de estas respuestas funcionó para mí. Después de aproximadamente una hora, descubrí algo muy insidioso:

Tengo una vista de tabla dentro de una celda de otra vista de tabla. Decidí hacer una vista envolvente que contenga la vista de tabla interna, entre otras cosas. Llamé a esta vista contentView y la conecté en el xib.

Resulta que UITableViewCell ya tiene un contentView y hace cosas raras con él. El problema se resolvió por sí solo cuando cambié el nombre de la propiedad a mainContentView y volví a conectar la vista a esta propiedad renombrada.

xytor
fuente
4

En mi caso, calculo dinámicamente la altura de la TableView's SuperViewen el tiempo de carga. Debido a un error de cálculo, TableViewse colocó fuera de la SuperView. Se TableViewdibujó bien, sin embargo, toda la interacción se deshabilitó (y didSelectRowAtIndexPathnunca se llamó). Muy difícil de detectar, ya que no hay indicación visual de que TableViewno sea "accesible".

GK100
fuente
4

En mi caso, el problema era que tenía una UITableViewCellsubclase y había implementado estos dos métodos: touchesBegan:withEvent:y touchesEnded:withEventmanejar una animación elegante al tacto. Pero olvidé agregar el [super touchesBegan:touches withEvent:event];método publicitario[super touchesEnded:touches withEvent:event]; para informar también al padre de la celda del toque.

Entonces, cambiar el código a siguiente resolvió mi 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
}
alternatiph
fuente
1
Puedo confirmar que esto me causó el problema del OP en particular
Josh Wolff
4

En mi caso, la solución fue cambiar NO a SÍ en la siguiente función.

iOS 9+

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
HonkyHonk
fuente
Este fue mi problema también. Tengo una implementación de múltiples vistas de tabla y olvidé separar las dos vistas de tabla en este método.
probado el