Comment puis-je déboguer l'erreur "Sélecteur non reconnu envoyé à l'instance"

100

Je crée une vue de cellule de tableau personnalisée pour ma vue de tableau. Après avoir connecté une vue d'image d'une cellule personnalisée (dans le storyboard) à mon code en swift, j'obtiens l'erreur suivante.

[UITableViewCellContentView image]: unrecognized selector sent to instance 0x7fb4fad7fd20'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010ccbb3f5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010e7e9bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010ccc250d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010cc1a7fc ___forwarding___ + 988
    4   CoreFoundation                      0x000000010cc1a398 _CF_forwarding_prep_0 + 120
    5   UIKit                               0x000000010d7d8881 -[UITableViewCell _marginWidth] + 151
    6   UIKit                               0x000000010d7ca23d -[UITableViewCell _separatorFrame] + 70
    7   UIKit                               0x000000010d7ca6fa -[UITableViewCell _updateSeparatorContent] + 360
    8   UIKit                               0x000000010d7d4e85 -[UITableViewCell _setSectionLocation:animated:forceBackgroundSetup:] + 1174
    9   UIKit                               0x000000010d634ea8 __53-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke + 1822
    10  UIKit                               0x000000010d5b5eae +[UIView(Animation) performWithoutAnimation:] + 65
    11  UIKit                               0x000000010d63477b -[UITableView _configureCellForDisplay:forIndexPath:] + 312
    12  UIKit                               0x000000010d63bcec -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 533
    13  UIKit                               0x000000010d61b7f1 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2846
    14  UIKit                               0x000000010d63165c -[UITableView layoutSubviews] + 213
    15  UIKit                               0x000000010d5be199 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
    16  QuartzCore                          0x00000001114b6f98 -[CALayer layoutSublayers] + 150
    17  QuartzCore                          0x00000001114abbbe _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    18  QuartzCore                          0x00000001114aba2e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
    19  QuartzCore                          0x0000000111419ade _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
    20  QuartzCore                          0x000000011141abea _ZN2CA11Transaction6commitEv + 390
    21  QuartzCore                          0x000000011141b255 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
    22  CoreFoundation                      0x000000010cbf0347 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    23  CoreFoundation                      0x000000010cbf02a0 __CFRunLoopDoObservers + 368
    24  CoreFoundation                      0x000000010cbe60d3 __CFRunLoopRun + 1123
    25  CoreFoundation                      0x000000010cbe5a06 CFRunLoopRunSpecific + 470
    26  GraphicsServices                    0x0000000110daa9f0 GSEventRunModal + 161
    27  UIKit                               0x000000010d545550 UIApplicationMain + 1282
    28  TestWork                          0x000000010caa432e top_level_code + 78
    29  TestWork                          0x000000010caa436a main + 42
    30  libdyld.dylib                       0x000000010efc3145 start + 1
    31  ???                                 0x0000000000000001 0x0 + 1
)

Pouvez-vous me dire comment résoudre cette erreur?

Je vous remercie.

J'ajoute un point d'arrêt d'exception dans mon projet.

C'est la ligne où ça casse.

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = self.tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as ItemTableViewCell  <---------------

Mais je n'utilise pas «image» dans mon code.

n179911
la source
2
vous appelez image]quelque part ... mais sur le mauvais objet. la première ligne de l'erreur vous en dit long
ccwasden
1
Arrêtez d'appeler [image] sur UITableViewCellContentView - cela réglerait le problème. Montrez-nous le code à l'origine de ce crash.
Grzegorz Krukowski
1
Je pense que vous avez utilisé une image dans tableViewCell mais cette image n'est peut-être pas dans votre ensemble.
Nand Parikh le

Réponses:

102

Essayez de définir un point d'arrêt symbolique -[NSObject(NSObject) doesNotRecognizeSelector:]. Cliquez simplement [+]dans le coin inférieur gauche du navigateur de points d'arrêt pour ajouter un point d'arrêt. Cliquez ensuite sur «Ajouter un point d'arrêt symbolique». La reproduction de votre plantage maintenant devrait vous donner une meilleure idée de l'emplacement du problème dans votre code.

entrez la description de l'image ici

dbart
la source
17
Pourrait également simplement ajouter un point d'arrêt d'exception .
rebello95
1
J'ai sauvé ma journée, mon frère.
AntiMoron
1
Merci c'est tellement utile
Mohd Sadham
35

Vous pouvez facilement suivre ces plantages en utilisant Exception Breakpoints.

Ouvrez le Breakpoint Navigatoret ajoutez le

entrez la description de l'image ici

Une fois que vous avez ajouté le point d'arrêt d'exception, l'option sera ouverte pour choisir le Exception.

entrez la description de l'image ici

Sélectionnez Objective-C.

Exécutez le code et plantez l'application, le point d'arrêt vous arrêtera au point où le code se bloque.

Vatsal K
la source
Cela se passe sur la ligne 1 d'AppDelegate. Et maintenant? :(
Daniel Springer
Pouvez-vous montrer une partie de votre code écrit dans AppDelegate? Où il met en pause le point d'arrêt. Et aussi les journaux.
Vatsal K
il s'arrête sur la ligne 1, où le délégué de l'application est déclaré
Daniel Springer
Il y a des cas où il s'arrête, à cause de certains frameworks, mais ne vous inquiétez pas, vous devrez peut-être appuyer sur le bouton Continuer 3 à 4 fois pour exécuter l'application.
Vatsal K
Ce n'est pas une erreur dans ce cas, certains anciens frameworks posent ce genre de problème. Essayez de mettre à jour vos anciens frameworks avec de nouveaux / mis à jour. Cela devrait résoudre le problème.
Vatsal K
30

La première étape critique consiste à analyser le message d'erreur:

[UITableViewCellContentView image]: unrecognized selector sent to instance

Cela vous indique que le "message" a imageété "envoyé" à un objet de la classe UITableViewCellContentView. (En d'autres termes, une tentative a été effectuée pour appeler la méthode imagesur un objet de la classe UITableViewCellContentView.)

La première chose à se demander est "Est-ce que cela a du sens?" Il se peut que la classe nommée ait une Imageméthode, mais pas une imageméthode, et donc le mauvais nom de méthode a été utilisé lors de l'appel. Ou il se peut que la méthode nommée soit someMethod:someParm:, mais que la classe l'implémente someMethod:someParm:anotherParm:, ce qui signifie qu'un paramètre a été omis lors de l'appel.

Le plus souvent, cependant, la classe nommée n'a aucune méthode ressemblant même vaguement à la méthode nommée, ce qui signifie qu'un pointeur vers le mauvais objet a été utilisé dans l'appel échoué.

Par exemple, on pourrait faire:

NSArray* myArray = [myDictionary objectForKey:@"values"];
NSString* myString = [myArray objectAtIndex:5];

Et obtenez une erreur du type:

[__NSDictionaryI objectAtIndex:] unrecognized selector sent to instance

car l'objet récupéré myDictionaryétait, en fait, un NSDictionary, pas le NSArray attendu.

Le plus déroutant, malheureusement, est lorsque ce type d'erreur se produit profondément dans le code système de l'interface utilisateur plutôt que dans votre propre code. Cela peut se produire lorsque vous avez transmis le mauvais objet à une interface système ou que vous avez peut-être configuré la mauvaise classe dans Interface Builder ou ailleurs.

Hot Licks
la source
6

Une autre raison possible est que l'objet d'origine a été détruit et qu'un autre objet a été alloué à la même adresse mémoire. Ensuite, votre code envoie le message, pensant qu'il a toujours un pointeur vers l'ancien objet, et Objective-C lève une exception car le nouvel objet ne comprend pas ce message.

Pour diagnostiquer ce problème, exécutez le Profiler avec la détection «Zombies».

Bryan
la source
2

Swift 5.0

Vous pouvez utiliser Introspection pour savoir si l'objet répond ou non à un sélecteur particulier.

let canWork = yourObject.respondsToSelector(Selector("image"))   // true

Seulement s'il est vrai que le code fonctionnera ... sinon il plantera à coup sûr

Saranjith
la source
1

Dans ces scénarios, j'ai trouvé utile d'examiner deux choses

  1. La pile d'appels
  2. Les variables locales (et leurs types) à chaque frame de pile

Lorsque j'ai eu cette erreur, c'est généralement parce que j'ai envoyé un message à une instance de Type A, alors que je m'attendais à Type B.

Dans ce scénario spécifique, vous ne répondez peut-être pas à une exigence d'une classe parente (étant donné que votre instance de ItemTableViewCell hérite très probablement).

Pouvez-vous nous montrer le code de votre classe ItemTableViewCell?

abc
la source
1

Vous pouvez utiliser le code suivant pour déclarer la variable:

let noteListTableViewCellobject = "NoteListTableViewCell";` `// Note listTablecell create custom cell`

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

    var cell:NoteListTableViewCell? = tableView.dequeueReusableCellWithIdentifier(noteListTableViewCellobject) as? NoteListTableViewCell

    if (cell == nil) {
        let nib:Array = NSBundle.mainBundle().loadNibNamed("NoteListTableViewCell", owner: self, options: nil)
        cell = nib[0] as? NoteListTableViewCell
    }
}
Shelke Yogesh
la source
0

J'ai eu le même problème, et cela a fonctionné pour moi:

Remplacez isEqual dans votre SKScene:

- (BOOL)isEqual:(id)other {

    if (![other isMemberOfClass:[SKScene class]]) {
        return false;
    }
    return [super isEqual:other];
}
Razvan
la source
0

Vous devez passer indexPathpour déclarer l'objet de la cellule tableview.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

    return cell
}
Rohit Parsana
la source