web-dev-qa-db-fra.com

-didSelectRowAtIndexPath: ne pas être appelé

J'écris une application iOS avec une vue sous forme de tableau dans un onglet. Dans ma 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 sous forme de tableau est cependant en train d'être renseignée, je sais donc que d'autres méthodes tableView de mon contrôleur sont en cours d'appel.

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

274
Matt Pfefferle

Il semble que la classe n’est peut-être pas la UITableViewDelegate pour cette vue tabulaire, bien que UITableViewController soit censé la définir automatiquement.

Avez-vous une chance de réinitialiser le délégué dans une autre classe?

92
Hunter

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

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

530
CGee

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

UITableView selection kind

Doit être Single Selection pour la sélection normale, devrait pas être No Selection.

472
Dennis Krut

Une autre possibilité est qu'un UITapGestureRecognizer consomme 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 seraient toujours surlignées en bleu comme si les robinets passaient.

279
bugloaf

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

(Particulièrement 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.

149
Old McStopher

Si le problème survient avec UITapGestureRecognizer, vous pouvez résoudre ce problème:

  • dans le Storyboard:

enter image description here

dans le code avec Objective-C:

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

[tap setCancelsTouchesInView:NO];

dans le code avec Swift:

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

tap.cancelsTouchesInView = false
83

J'ai rencontré deux choses dans cette situation.

  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 table.

  2. Vous pourriez avoir un UIView dans votre ligne qui est un premier répondant et qui enlève vos clics. Dites un UIButton ou quelque chose de similaire.

63
gilm

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

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

Il doit s'agir de return indexPath, sinon -tableView:didSelectRowAtIndexPath: n'est pas appelé.

44
JackPearse

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

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

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

J'ai rencontré un problème où, après des mois sans regarder mon code, j'avais oublié d'appliquer la méthode suivante en raison de certaines exigences inutiles.

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

Il doit renvoyer OUI pour une ligne afin de le sélectionner. 

27
cpt.neverm1nd

VOUS DEVEZ sélectionner ces options

 enter image description here

mais si vous souhaitez mettre UITableViewnot en surbrillance en cliquant, vous devez modifier les propriétés UITableViewCell.

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

 enter image description here

24
Mohsin Qureshi

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

La raison en était d'utiliser UITapGestureRecognizer. Je voulais que le clavier disparaisse lorsque j'ai tapé ailleurs. J'ai réalisé que cela annulait toutes les actions tapées, c'est pourquoi, la fonction didSelectRowAtIndexPath n'a pas appelé.

Lorsque je commente les lignes liées à UITapGestureRecognizer, cela fonctionne. De plus, vous pouvez vérifier dans la fonction de UITapGestureRecognizer selector si le tapoté est UITableViewCell ou non.

19
Jeyhun Karimov

Si vous avez le même problème que moi: Apparemment, cette méthode ne sera pas appelée si votre tableView est en mode édition. Vous devez définir allowSelectionDuringEditing sur true.

Via cette question: Lors de la modification, `UITableView` n’appelle pas didSelectRowAtIndexPath ??

19
spiralstairs

J'avais mis une UITapGestureRecognizer sur ma vue de table pour ignorer le clavier empêchant l'appel de didSelectRowAtIndexPath:. J'espère que ça aide quelqu'un.

18
Groot

Pour Xcode 6.4, Swift 1.2. La sélection "tag" a été modifiée dans IB. Je ne sais pas comment et pourquoi. En le réglant sur "Sélection unique", les cellules de la vue tableau ont été sélectionnées à nouveau  enter image description here

11
MB_iOSDeveloper

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];
10
Carlos

Même si une autre réponse a été acceptée, je vais ajouter 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 l'affectation de 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 une référence pour l'ARC. Par conséquent, si c'est la seule référence, le contrôleur sera libéré. 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 consiste à garder le contrôleur avec une référence forte quelque part ailleurs, jusqu'à ce que vous soyez sûr de ne plus en avoir besoin.

10
Andrew Gorcester

Mon problème était aucun de ce qui précède. Et si boiteux. Mais je pensais que je l'énumérerais ici au cas où cela aiderait quelqu'un. 

J'ai un tableViewController qui est mon contrôleur "de base" puis je crée des sous-classes de ce contrôleur. J'écrivais tout mon code dans la routine tableView:didSelectRowAtIndexPath de la classe "base". Oubliant complètement que, par défaut, cette routine avait également été créée (même si aucun code ne faisait rien) dans toutes mes sous-classes. Ainsi, lorsque j'ai exécuté mon application, la version sous-classe du code n'a pas fonctionné 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 mt "base" et je suis en affaires.

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

9
Steve

Donner mes 2 cents à ce sujet.

J'avais un Custom UITableViewCell et il y avait un bouton couvrant toute la cellule. Ainsi, lorsque le contact a eu lieu, le bouton était sélectionné et non la cellule.

Supprimez le bouton ou, dans mon cas, j’ai défini False sur Interaction utilisateur, ce qui a permis à la cellule d’être sélectionnée.

8
gmogames

Dans mon cas, didSelctRowAtIndexPath n'appelle pas parce que j'ai sélectionné none dans la propriété Selection de tableView, défini sur single selection a résolu mon problème.

 enter image description here

8
Naveed Ahmad

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

J'ai custom cell, où la case " Interaction utilisateur activée " était désactivée. Alors, je viens de l'allumer. Bonne chance. 

8
HotJard

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

7
user486646

Je sais que c'est vieux et le problème a été résolu, mais 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 fonctionne ensuite! presque comme Windows :)

5
Lukasz

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

5
yvetterowe

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

iOS 9+

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

Aucune de ces réponses n'a fonctionné pour moi. Après environ une heure, j'ai découvert 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 je l'ai connectée à xib.

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

4
xytor

Dans mon cas, je calcule de manière dynamique la hauteur de la TableView de SuperView au moment du chargement. En raison d'une erreur de calcul, la TableView était positionnée en dehors de la SuperView. La variable TableView était correcte, mais toutes les interactions étaient désactivées (et didSelectRowAtIndexPath n'a jamais été appelé). Très difficile à détecter, car rien n'indique que la TableView ne soit pas "accessible".

4
GK100

Assurez-vous d'avoir implémenté tableView:didSelectRowAtIndexPath et non tableView:didDeSelectRowAtIndexPath

Cela m'est arrivé à plus de quelques reprises !!

4
SleepsOnNewspapers

Une autre erreur que vous auriez pu commettre (comme je l’ai fait): si vous définissez une transition dans la cellule, didSelectRowAtIndexPath n’est pas appelée. Vous devez plutôt définir vos suites sur le contrôleur de vue.

4
juanignaciosl

Ok, mise à jour ici car je viens de rencontrer ce problème, et mon problème était légèrement différent de celui trouvé ici. 

J'ai regardé dans IB et j'ai vu que mon délégué était défini sur WAS, mais il avait été défini de manière incorrecte sur VIEW au lieu de File's Owner (cliquez avec le bouton droit de la souris sur la vue tabulaire pour voir où le délégué pointe).

J'espère que ça aide quelqu'un

3
tbone

Faites attention aux propriétés UITableView du storyboard, ce qui s’est passé dans mon cas, c’est que la combox du storyboard a été sélectionnée comme "Sélection: sélection unique", ce qui ne permet pas à la méthode didSelectRowAtIndexPath de s’exécuter.

3
Diego Maye

Si vous avez une cellule personnalisée, n'oubliez pas de définir UserInteractionEnabled dans Xib (ou via le code) pour la cellule.

2
giuseppe

Dans mon cas, une seule cellule avait ce problème. La cellule inclut la sortie UITextView en mode lecture seule. Bien que ce soit en lecture seule avant le robinet. En tapotant, le clavier se leva. Il s'est avéré qu'il était toujours nécessaire de désactiver l'interaction.

cell.content.scrollEnabled = NO;
cell.content.editable = NO;
cell.content.userInteractionEnabled = NO;
cell.content.delegate = nil;

[cell.content resignFirstResponder];

2
Imju

Il y a des indices incroyables et des réponses dans ce billet (peut-être l'une des meilleures discussions que j'ai vues!). Les indices ici m'ont permis de comprendre en quoi consistait mon problème, mais j'ai passé de nombreuses heures à baver sur mon clavier pour essayer de découvrir le question, qui était similaire à d'autres postes. Cependant, j'ai finalement découvert que c'était un peu différent, alors je voulais partager si d'autres le rencontraient aussi.

Il s'est avéré que mon problème était que, dans le code, une super-classe ajoutait une "vue d'erreur" plein écran qui n'était pas masquée, mais transparente. Cependant, comme il se trouvait au-dessus de la vue de table et que "action de l'utilisateur" était défini sur OUI, cela interceptait mes interventions sur la vue de la table.

J'ai diagnostiqué cela en utilisant le super bouton "Hiérarchie de la vue de débogage" de Xcode. Voici une capture d'écran avec des annotations qui expliquent, espérons-le, ce que j'ai fait et comment j'ai finalement diagnostiqué le problème.

En code, je devais simplement faire:

errorMessageView.setUserInteractionEnabled = NO;
// or
errorMessageView.hidden = YES;

 Debug View Hierarchy

2
DustinB

Si la cellule sur laquelle vous cliquez est en surbrillance mais que la fonction n'est toujours pas appelée, vérifiez bien la signature de votre fonction. Ça devrait ressembler à ça:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
2
Jeb_is_a_mess

Ce n'était probablement que dans mon cas, mais j'avais rechargé certains fichiers à partir d'une sauvegarde et tout ne fonctionnait pas, y compris celui-ci. Après un nettoyage complet (Produit> Nettoyer ou Maj + Commande + K), cela a fonctionné. Quelque chose s'est probablement foiré dans un en-tête précompilé. Les chances sont que ce n'est pas le problème pour vous, mais ça vaut le coup.

2
shim

Vérifiez si votre viewController a la méthode suivante:

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

si vous renvoyez "NON", didSelectRow ne sera pas appelé

2
Srinath Mithra

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

Donc 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
}
2
alternatiph

Vérifiez si -heightForRowAtIndexPath ne renvoie pas 0.

2
shyamsundar1988

J'avais ce problème par intermittence. Parfois, si vous touchez une cellule, elle sera sélectionnée. Parfois, il ne recevrait pas l'événement tactile. 

J'utilise une fonctionnalité introduite dans ios8 appelée cellules à dimensionnement automatique. Je suis tombé sur ce blog post qui souligne que:

Lorsque la vue tableau est affichée pour la première fois, vous pouvez trouver certaines des cellules ne sont pas correctement dimensionnés. Mais lorsque vous faites défiler la vue tableau, le nouveau fichier les cellules sont affichées avec une hauteur de ligne correcte. Pour résoudre ce problème, vous pouvez forcer un rechargement après l'affichage de la vue:

override func viewDidAppear(animated: Bool) {
    tableView.reloadData()
}

Cela a résolu le problème pour moi. Même si l'affichage de la table était correctement rendu, la manipulation tactile (plus précisément hitTest de UITableView) semblait être soumise au bogue susmentionné.

1
benvolioT

Je viens d'avoir ce problème, mais cela ne s'est pas produit tout de suite. après avoir sélectionné quelques cellules, ils cesseraient d'appeler didSelectItemAtIndexPath. J'ai réalisé que le problème était que la vue de la collection avait allowsMultipleSelection défini sur TRUE. Comme les cellules n'étaient jamais désélectionnées, les futurs appels ne pouvaient plus appeler didSelectItemAtIndexPath.

1
Mark Bridges

Une autre possibilité folle: je courais mon application sur un iPhone 5S, et j'ai utilisé:

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

comme je l'ai toujours fait par le passé.

Cependant, je n'ai pas suffisamment regardé les avertissements de mon compilateur ... il a été dit que je devrais changer cette ligne en:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Compatibilité 64 bits! secoue le poing

Soyez à l'affût au cas où vous commenciez à vous arracher les cheveux.

1
karlbecker_com

J'ai eu un appel à cell.userInteractionEnabled enterré dans un code de table personnalisé.

Stupide, mais la plupart des insectes ne sont-ils pas?

1
HalR

J'ai répété toutes les réponses précédentes mais aucune d'entre elles ne m'a aidé. Après quelques essais et erreurs, j'ai trouvé une solution différente. J'avais un UIImageView couvrant toute la cellule (en arrière-plan). Par défaut, une interaction utilisateur est désactivée dans UIImageView. En activant la méthode de délégation d'interaction utilisateur imageviews -didSelectRowAtIndexPath: a été appelée à nouveau . eg.

cell.imgView.userInteractionEnabled = YES;
1
Yannick Winters

J'ai eu ce problème moi-même. J'avais construit les os de la vue dans IB (juste une vue et une vue tableau) et le délégué n'était pas défini. Je l'ai connecté au propriétaire de File et cela a fonctionné à merveille. ::enregistrer::

1
indigosplinter

Une autre cause possible semble être que la UITableView est intégrée à une UIScrollView. J'ai eu ce problème aujourd'hui parce que j'avais par inadvertance une vue de défilement au lieu d'une vue normale en tant que vue racine de mon contrôleur.

1
Taum

Dans mon cas, le problème était de déclarer la méthode privée.

Cela n'a pas fonctionné:

private func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

Cela a fonctionné:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
0
Prasanna Ramaswamy

Assurez-vous d'appeler reloadData sur le thread principal. Si vous appelez cette méthode à partir d'une méthode asynchrone (par exemple, une requête réseau), la vue sous forme de tableau peut ou non répondre correctement (dans certains cas, l'application peut même se bloquer).

Utilisez un bloc de code de thread principal pour effectuer l'appel reloadData, si l'appel est effectué dans un autre bloc de méthode (dont vous n'êtes pas sûr):

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [tableView reloadData];
}];
0
Supertecnoboff
  1. Ajouter @interface ExampleViewController () <UITableViewDelegate, UITableViewDataSource>

  2. Faire une délégation dans le storyboard

 enter image description here

  1. Ajouter le code

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
       NSString *cellText = cell.textLabel.text;
    }
    
0
dip

S'il vous plaît vérifier UITapGestureRecognizer. Dans mon cas, tapgesture a été ajouté pour la vue où tableview a été placée, ce qui consomme l'interaction utilisateur de UITableview comme didselect. Après la désactivation de tapgesture pour la vue, le délégué didselect a été déclenché.

0
Prasad.Jakka

J'ai lu toutes les réponses et suis tout à fait d'accord avec elles. Mais c'est tout à fait différent dans mon cas. J'avais un nouveau segue pour mon detailViewController lié directement à mon tableCell dans StoryBoard qui en était la cause Je devais donc retirer cette transition de ma cellule et la relier à la variable UITableViewController elle-même. Maintenant, en écrivant le code suivant ça marche,

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        // Do any operation
        performSegue(withIdentifier: "DetailSegue", sender: self)
    }

J'espère que cette solution aidera quelqu'un là-bas!

0
Sasi M

vous devez vérifier cette sélection doit être une sélection unique et l'édition ne doit pas être une sélection lors de l'édition et vous modifiez le paramètre dans les propriétés uttableviewcell ainsi que vous l'éditez dans le style de cellule de la vue tableau doit être personnalisé et l'identifiant doit être Rid et la section est none

0
ATIQ UR REHMAN

Je ne suis pas sûr que quelqu'un défile suffisamment pour voir cette réponse, mais comme c'est la question la plus populaire à propos de ce sujet et que la réponse n'était pas là, je vais l'ajouter:

À partir de Xcode 9/Swift 4, toutes les méthodes Objective-C doivent porter la marque @objc. Le compilateur fait un travail raisonnable en reconnaissant où il devrait être appliqué, mais il ne comprend pas l'héritage. Par exemple:

class Delegate: NSObject, UITableViewDelegate {
}

class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}

Cela ne générera aucun avertissement, crash ou erreur de construction. Cependant, votre ligne ne sera pas appelée tant que vous n'aurez pas ajouté @objc:

@objc class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}
0
Departamento B

J'avais un problème que le contrôle n'allait pas dans la ligne didselect après l'application du point d'arrêt. problème était en vue. J'ai enlevé le geste de l'onglet. alors ça a bien fonctionné

0
user2110847

dans le cas où j’ai commis une petite erreur, j’ai assigné:

tableView.isUserInteractionEnabled = false

cA devrait etre:

tableView.isUserInteractionEnabled = true
0
Vinayak Pal