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?
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?
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 ...
Une autre chose qui pourrait conduire au problème est le type de sélection non sélectionné:
Doit être Single Selection
pour la sélection normale, devrait pas être No Selection
.
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.
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
.
Si le problème survient avec UITapGestureRecognizer
, vous pouvez résoudre ce problème:
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
J'ai rencontré deux choses dans cette situation.
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.
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.
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é.
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;
}
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.
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.
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 ??
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.
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];
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.
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 ...
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.
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.
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:
.
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 :)
Si votre vue tableau est en mode d'édition (par exemple, [tableView setEditing:YES animated:NO];
), vous devez définir tableView.allowsSelectionDuringEditing = YES;
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;
}
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.
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".
Assurez-vous d'avoir implémenté tableView:didSelectRowAtIndexPath
et non tableView:didDeSelectRowAtIndexPath
Cela m'est arrivé à plus de quelques reprises !!
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.
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
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.
Si vous avez une cellule personnalisée, n'oubliez pas de définir UserInteractionEnabled dans Xib (ou via le code) pour la cellule.
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];
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;
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)
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.
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é
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
}
Vérifiez si -heightForRowAtIndexPath ne renvoie pas 0.
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é.
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
.
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.
J'ai eu un appel à cell.userInteractionEnabled enterré dans un code de table personnalisé.
Stupide, mais la plupart des insectes ne sont-ils pas?
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;
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::
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.
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) {
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];
}];
Ajouter @interface ExampleViewController () <UITableViewDelegate, UITableViewDataSource>
Faire une délégation dans le storyboard
Ajouter le code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
}
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é.
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!
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
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 }
}
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é
dans le cas où j’ai commis une petite erreur, j’ai assigné:
tableView.isUserInteractionEnabled = false
cA devrait etre:
tableView.isUserInteractionEnabled = true