-didSelectRowAtIndexPath: non appelé

295

J'écris une application iOS avec une vue tabulaire dans une vue à onglets. Dans mon UITableViewController, j'ai implémenté -tableView:didSelectRowAtIndexPath:, mais lorsque je sélectionne une ligne au moment de l'exécution, la méthode n'est pas appelée. La vue de table est cependant remplie, donc je sais que d'autres méthodes tableView de mon contrôleur sont appelées.

Quelqu'un a-t-il une idée de ce que j'ai pu foirer pour que cela se produise?

Matt Pfefferle
la source
79
vous pouvez également avoir un gestureRecognizer au-dessus de UITableView qui absorbe la sélection .. (l'une des possibilités)
M.Othman
Soyez prudent si la vue de table est en cours de remplissage, cela signifie que la DataSource est bien définie. La sélection fait partie des méthodes Délégué. Alors peut-être que le DataSource est bien défini mais pas le délégué!
Thomas Besnehard
1
Bonjour M.Othman, votre commentaire est exactement ce qui n'allait pas avec mon propre problème. Savez-vous comment faire fonctionner le reconnaissance gestuelle «avec» le UITableView?
yhl
15
Je remarque que si je reste appuyé, le robinet finit par appeler -didSelectRowAtIndexPath. J'ai compris le chapeau parce que j'ai un identificateur de geste de robinet sur la table et le geste doit d'abord échouer avant de recevoir le toucher. Bien que cela soit étrange, l'animation de sélection de table n'est pas affectée par le reconnaisseur de gestes.
Hlung
6
J'ai eu le même problème ici et j'ai eu la chance d'apprendre que vous ne pouvez pas avoir un gestureRecognizer au-dessus de l'UITableView. Merci M. Othman!
vnchopra

Réponses:

97

Il semble que la classe ne soit peut-être pas UITableViewDelegatepour cette vue de table, bien queUITableViewController soit censée la définir automatiquement.

Y a-t-il une chance que vous réinitialisiez le délégué dans une autre classe?

Hunter
la source
7
J'ai découvert que même si mon contrôleur était un UITableViewController, j'ai utilisé un vieux widget UIViewController dans UI Builder. Ça ne marche pas. Lorsque j'ai supprimé le widget UIViewController et déposé un UITableViewController à sa place, tout a fonctionné.
Matt Pfefferle
1
Un autre cas limite pour tout le monde - j'ai câblé le délégué en code et j'avais oublié que j'avais déjà câblé le délégué via le storyboard ... le dernier pour le définir gagne.
Oliver Dungey
1
pouvez-vous montrer comment "réinitialiser un délégué à une autre classe" s'il vous plaît? J'ai ce même problème et je n'arrive pas à le résoudre
Alfro
1
myTableViewController.tableView.delegate = xxx
Hunter
534

Juste au cas où quelqu'un aurait fait la même erreur stupide que moi:

Vérifiez si le nom de la méthode de ce que vous attendez didSelectpeut être obtenu accidentellement d' didDeselectune manière ou d'une autre. Il m'a fallu environ deux heures pour le découvrir ...

Dschee
la source
47
Même problème ici. C'est parce que XCode complète automatiquement la désélection avant la sélection.
user1021430
De même, j'avais défini allowSelection = false, ce qui, en plus de supprimer toute surbrillance de sélection, empêche également d'appuyer sur la cellule!
djinne95
503

Une autre chose qui pourrait conduire au problème n'est pas le type de sélection sélectionné:

Type de sélection UITableView

Devrait être Single Selectionpour une sélection normale, ne devrait pas êtreNo Selection .

Pour ce faire par programme, procédez comme suit:

tableView.allowsSelection = YES
Dennis Krut
la source
4
Je continue à courir parce que j'ai des scènes qui sont toujours en mode édition et j'oublie toujours de changer la valeur par défaut de "Aucune sélection pendant l'édition".
symétrique
3
Vous pouvez ajouter cette ligne dans votre méthode -viewDidLoad de viewControlller NSParameterAssert (self.tableView.allowsSelection);
Nikolay Shubenkov
pour ceux qui ont observé tableView.rx.itemSelected.subscribe n'a pas rappelé, c'est le problème et les correctifs ci-dessus
Dhilip
si utile lorsque vous reprenez une base de code et qu'il a du code à l'aide de boutons avec des balises et non de didSelectRow, avec cette sélection désactivée dans le storyboard 🙄
Nitin Alabur
est ce comportement par défaut de tableView?
Frostmourne
296

Une autre possibilité est qu'un UITapGestureRecognizer puisse manger les événements, comme c'était le cas ici: https://stackoverflow.com/a/9248827/214070

Je ne soupçonnais pas cette cause, car les cellules du tableau étaient toujours surlignées en bleu comme si les robinets passaient.

2 tours
la source
C'était mon problème! Merci beaucoup!! Je veux dire que cela fonctionnait clairement avant, mais il a cessé de fonctionner après avoir implémenté UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector (disableKeyboard)]; [self.view addGestureRecognizer: appuyez sur];
coolcool1994
26
J'ai eu le même problème que vous @ coolcool1994 vient d'être implémenté [appuyez sur setCancelsTouchesInView: NO]; et résolu le problème.
nizx
Merci, ça m'aide. Dans mon cas, didSelectRowAtIndexPathcela ne fonctionne pas seulement après la suppression de la cellule commitEditingStyle. Ensuite, je fais UITapGestureRecognizeret tapAction:suis arrivé indexPathde sender.view( [self.tableView indexPathForCell:sender.view]) et appelle[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon
1
C'était aussi mon problème .. ajouter du code pour supprimer la tapgesture dans tableview et cela fonctionnait comme un charme - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * gesture = [[UITapGestureRecogn ] init]; gesture.cancelsTouchesInView = NO; [self.tableView addGestureRecognizer: geste]; }
Udaya Sri
6
Merci @nizx, dans swift 4 tap.cancelsTouchesInView = false
Ariven Nadar
150

Toutes les bonnes réponses, mais il y en a une de plus à rechercher ...

(En particulier lors de la création d'un UITableView par programme)

Assurez-vous que tableView peut répondre à la sélection en définissant [tableView setAllowsSelection:YES];ou en supprimant toute ligne qui le définit NO.

Old McStopher
la source
9
J'ajouterais setAllowsSelectionDuringEditing:à la liste (lorsque tableview est en mode édition)
alex-i
Je vous remercie! Dans IB, j'ai dû changer la valeur de la section "Sélection" en Single Selection.
Sasho
90

Si le problème survient, UITapGestureRecognizervous pouvez résoudre ce problème:

  • dans Storyboard:

entrez la description de l'image ici

en code avec Objective-C:

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

[tap setCancelsTouchesInView:NO];

en code avec Swift:

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

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

J'ai rencontré deux choses dans ces situations.

  1. Vous avez peut-être oublié d'implémenter le protocole UITableViewDelegate, ou il n'y a pas de sortie de délégation entre votre classe et votre vue de table.

  2. Vous pouvez avoir une UIView dans votre ligne qui est un premier répondant et supprime vos clics. Dites un bouton UIB ou quelque chose de similaire.

gilm
la source
5
Cela a commencé à se produire sur iOS 7, la désactivation de "Interaction utilisateur activée" des vues dans contentView a corrigé ce problème.
Kof
1
@Kof l'a cloué. La création d'un UITableViewCell dans le générateur d'interface de Xcode 5 le crée avec l'interaction utilisateur activée = OUI. Mauvais Xcode 5!
jsd
44

J'ai eu le même problème. Et c'était difficile à trouver. Mais quelque part dans mon code était le suivant:

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

Ça doit être return indexPath, sinon -tableView:didSelectRowAtIndexPath:on n'appelle pas.

JackPearse
la source
2
pour did SelectRow At IndexPath, la signature correcte est: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994
Pour moi, cela ne commencerait pas à appeler tableView: didSelectRowAtIndexPath jusqu'à ce que je supprime entièrement
willSelectRowAtIndexPath
38

Si vous avez ajouté un gestureRecognizer au-dessus de UITableView, didSelectRowAtIndexPathil ne sera pas appelé.

Vous devez donc utiliser la méthode déléguée gestureRecognizer pour éviter de toucher dans une vue particulière.

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

J'ai rencontré un problème où, après des mois de non-consultation de mon code, j'ai oublié que j'avais implémenté la méthode suivante en raison de certaines exigences qui n'étaient pas nécessaires

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

Il doit retourner OUI pour une ligne afin de la sélectionner.

cpt.neverm1nd
la source
24

VOUS DEVEZ sélectionner ces options

entrez la description de l'image ici

mais si vous ne souhaitez UITableViewpas mettre en surbrillance en cliquant, vous devez modifier les UITableViewCellpropriétés.

Choisissez l'option Aucune pour la sélection comme ci-dessous

entrez la description de l'image ici

Mohsin Qureshi
la source
20

J'avais mis une vue UITapGestureRecognizersur ma table pour fermer le clavier qui empêchait didSelectRowAtIndexPath:d'être appelé. J'espère que cela aide quelqu'un.

Groot
la source
19

J'ai eu le même problème,

La raison était l'utilisation de UITapGestureRecognizer. Je voulais que le clavier disparaisse lorsque je tapotais ailleurs. J'ai réalisé que cela annule toutes les actions de prise, c'est pourquoi, la didSelectRowAtIndexPathfonction n'a pas été appelée.

Lorsque je commente les lignes liées à UITapGestureRecognizer, cela fonctionne. De plus, vous pouvez vérifier dans la fonction UITapGestureRecognizer selectorsi le taraudé est UITableViewCellou non.

Jeyhun Karimov
la source
14

Dans mon cas, didSelctRowAtIndexPath n'appelant pas est dû au fait que je n'en ai sélectionné aucun dans la propriété Selection de tableView, réglé sur une seule sélection résolu mon problème

entrez la description de l'image ici

Naveed Ahmad
la source
11

Pour Xcode 6.4, Swift 1.2. La "balise" de sélection a été modifiée dans IB. Je ne sais ni comment ni pourquoi. Le paramétrer sur "Sélection unique" a rendu mes cellules de vue tabulaire sélectionnables à nouveau. entrez la description de l'image ici

MB_iOSDeveloper
la source
10

Même si une autre réponse a été acceptée, j'ajouterai un autre problème possible et une solution pour les personnes qui observent ce problème:

Si le comptage automatique des références (ARC) est activé, vous pouvez constater que même après avoir assigné votre contrôleur en tant que délégué de la vue, les messages de la vue au contrôleur ne sont pas reçus car ARC supprime le contrôleur. Apparemment, le pointeur délégué de UITableView ne compte pas comme référence pour l'ARC, donc si c'est la seule référence à celui-ci, le contrôleur sera désalloué. Vous pouvez vérifier si cela se produit ou non en implémentant la méthode dealloc sur le contrôleur et en y définissant un point d'arrêt ou un appel NSLog.

La solution est de garder une trace du contrôleur avec une référence forte ailleurs, jusqu'à ce que vous soyez sûr que vous n'en aurez plus besoin.

Andrew Gorcester
la source
Le contrôleur est-il récupéré alors que sa vue est toujours affichée? Cela peut-il réellement arriver?
Drux
@Drux Yep! Quand cela m'est arrivé, c'était presque la première version d'Obj-C avec la collecte des ordures utilisée sur iOS et honnêtement, ils n'ont pas fait un excellent travail. De nombreuses références étaient explicitement ou implicitement "faibles" qui, à mon avis, auraient dû être solides. Ce qui a conduit à des bizarreries comme la collecte des ordures d'objets en cours d'utilisation par la couche d'affichage. Je n'ai pas fait de travail iOS depuis un moment, donc je n'ai aucune idée si cela se produit toujours sur la dernière version.
Andrew Gorcester
Mon code a un problème de taille de mémoire croissant et j'en ai résolu un peu et ailleurs dans le code juste après que didSelect ne sera pas appelé la première fois seulement. Je ne sais pas si cela justifie le problème ou non.
Amber K
10

N'oubliez pas de définir la source de données et le délégué dans la méthode viewDidLoad comme suit:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];
Carlos
la source
J'appelais Datasource mais pas délégué ... merci!
Gmeister4
9

Mon problème n'était rien de ce qui précède. Et tellement boiteux. Mais je pensais que je le listerais ici au cas où cela aiderait quelqu'un.

J'en ai un tableViewControllerqui est mon contrôleur "de base" puis je crée des sous-classes de ce contrôleur. J'écrivais tout mon code dans la tableView:didSelectRowAtIndexPathroutine de la classe "base". Oubliant complètement que par défaut cette routine avait également été créée (mais sans code qui faisait quoi que ce soit) dans toutes mes sous-classes également. Ainsi, lorsque j'ai exécuté mon application, elle a exécuté la version de sous-classe du code, n'a rien fait et m'a rendu triste. Alors bien sûr, une fois que j'ai supprimé la routine des sous-classes, elle a utilisé la routine de classe "base" de mt et je suis en affaires.

Je connais. Ne riez pas. Mais peut-être que cela sauvera quelqu'un l'heure que j'ai perdue ...

Steve
la source
8

Donner mes 2 cents à ce sujet.

J'avais un UITableViewCell personnalisé et il y avait un bouton couvrant toute la cellule, donc quand le toucher s'est produit, le bouton a été sélectionné et non la cellule.

Soit supprimer le bouton ou dans mon cas, j'ai défini l'option Interaction utilisateur sur false sur le bouton, de cette façon la cellule était celle sélectionnée.

gmogames
la source
8

Si vous lisez ceci, cela ne résout toujours pas le problème.

J'ai une cellule personnalisée , où la case " Interaction utilisateur activée " était désactivée. Donc, je viens de l'allumer. Bonne chance.

HotJard
la source
7

Je viens de l'avoir et comme cela m'est arrivé dans le passé, cela n'a pas fonctionné car je n'ai pas prêté attention à la saisie semi-automatique lorsque j'essaie d'ajouter la méthode et je finis par implémenter tableView:didDeselectRowAtIndexPath: au lieu de tableView:didSelectRowAtIndexPath:.

utilisateur486646
la source
7

Assurez-vous que vous avez mis en œuvre tableView:didSelectRowAtIndexPathet nontableView:didDeSelectRowAtIndexPath

Cela m'est arrivé à plusieurs reprises !!

SleepsOnNewspapers
la source
5

Je sais qu'il est ancien et que le problème a été résolu, mais qu'il y avait un problème similaire, je pensais que le problème était avec mon UITableViewCell personnalisé, mais la solution était complètement différente - je redémarre XCode :) et puis ça marche! presque comme Windows :)

Lukasz
la source
5

Si votre vue tableau est en mode édition (par exemple [tableView setEditing:YES animated:NO];), vous devez définirtableView.allowsSelectionDuringEditing = YES;

yvetterowe
la source
4

Une autre erreur que vous auriez pu faire (comme je l'ai fait): si vous définissez un enchaînement à la cellule, didSelectRowAtIndexPathn'est pas appelé. Vous devez plutôt définir vos séquences sur le contrôleur de vue.

juanignaciosl
la source
4

Aucune de ces réponses n'a fonctionné pour moi. Après environ une heure, j'ai compris quelque chose de très insidieux:

J'ai une vue de table à l'intérieur d'une cellule d'une autre vue de table. J'ai décidé de créer une vue englobante contenant, entre autres, la vue de la table interne. J'ai appelé cette vue contentView et l'ai branchée dans le xib.

Il s'avère que UITableViewCell a déjà une contentView et fait des choses bizarres avec. Le problème s'est résolu lorsque j'ai renommé la propriété en mainContentView et reconnecté la vue à cette propriété renommée.

xytor
la source
4

Dans mon cas, je calcule dynamiquement la hauteur du TableViews SuperViewau moment du chargement. En raison d'une erreur de calcul, le a TableViewété positionné à l'extérieur du SuperView. Le a TableViewété très bien dessiné, mais toutes les interactions ont été désactivées (et didSelectRowAtIndexPathn'ont jamais été appelées). Très difficile à détecter, car rien n'indique visuellement qu'il TableViewn'est pas "accessible".

GK100
la source
4

Dans mon cas, le problème était que j'avais une UITableViewCellsous-classe et j'avais implémenté ces deux méthodes: touchesBegan:withEvent:& touchesEnded:withEventpour gérer une animation fantaisie au toucher. Mais j'avais oublié d'ajouter la [super touchesBegan:touches withEvent:event];méthode ad[super touchesEnded:touches withEvent:event]; pour informer également le parent de la cellule du toucher.

Changer le code en suivant a résolu mon problème:

-(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
la source
1
Peut confirmer que cela a causé le problème de l'OP pour moi en particulier
Josh Wolff
4

Dans mon cas, la solution consistait à remplacer NON par OUI dans la fonction ci-dessous.

iOS 9+

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
HonkyHonk
la source
C'était aussi mon problème. J'ai une implémentation de tableView multiple et j'ai oublié de séparer les deux tablesViews dans cette méthode.
testée