Wie kann ich den Fehler "Nicht erkannter Selektor an Instanz gesendet" debuggen?

100

Ich erstelle eine benutzerdefinierte Tabellenzellenansicht für meine Tabellenansicht. Nachdem ich schnell eine Bildansicht einer benutzerdefinierten Zelle (im Storyboard) mit meinem Code verbunden habe, wird der folgende Fehler angezeigt.

[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
)

Können Sie mir bitte sagen, wie ich diesen Fehler beheben kann?

Danke dir.

Ich füge meinem Projekt einen Ausnahme-Haltepunkt hinzu.

Dies ist die Linie, in der es bricht.

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

Aber ich verwende kein 'Bild' in meinem Code.

n179911
quelle
2
Sie rufen image]irgendwo an .. aber auf dem falschen Objekt. Die erste Zeile des Fehlers sagt Ihnen, dass viel
ccwasden
1
Hören Sie auf, [image] in UITableViewCellContentView aufzurufen - das würde das Problem beheben. Zeigen Sie uns den Code, der diesen Absturz verursacht.
Grzegorz Krukowski
1
Ich denke, Sie haben ein Bild in tableViewCell verwendet, aber dieses Bild befindet sich möglicherweise nicht in Ihrem Bundle.
Nand Parikh

Antworten:

102

Versuchen Sie, einen symbolischen Haltepunkt zu setzen -[NSObject(NSObject) doesNotRecognizeSelector:]. Klicken Sie einfach [+]in die untere linke Ecke des Haltepunktnavigators, um einen Haltepunkt hinzuzufügen. Klicken Sie dann auf "Symbolischen Haltepunkt hinzufügen". Wenn Sie Ihren Absturz jetzt reproduzieren, sollten Sie eine bessere Vorstellung davon haben, wo in Ihrem Code das Problem auftritt.

Geben Sie hier die Bildbeschreibung ein

dbart
quelle
17
Könnte auch nur einen Ausnahme-Haltepunkt hinzufügen .
rebello95
1
Hat meinen Tag gerettet, Bruder.
AntiMoron
1
Vielen Dank, es ist so nützlich
Mohd Sadham
35

Sie können solche Abstürze einfach mit verfolgen Exception Breakpoints.

Öffnen Sie das Breakpoint Navigatorund fügen Sie das hinzu

Geben Sie hier die Bildbeschreibung ein

Sobald Sie den Ausnahme-Haltepunkt hinzugefügt haben, können Sie die Option auswählen Exception.

Geben Sie hier die Bildbeschreibung ein

Wählen Sie Objective-C.

Führen Sie den Code aus und stürzen Sie die Anwendung ab. Der Haltepunkt stoppt Sie bis zu dem Punkt, an dem der Code abstürzt.

Vatsal K.
quelle
Es passiert in AppDelegate Zeile 1. Was nun? :(
Daniel Springer
Können Sie einen Teil Ihres in AppDelegate geschriebenen Codes anzeigen? Wo der Haltepunkt angehalten wird. Und auch die Protokolle.
Vatsal K
Es wird in Zeile 1 angehalten, in der der App-Delegierte deklariert wird
Daniel Springer,
Es gibt einige Fälle, in denen es aufgrund einiger Frameworks angehalten wird. Machen Sie sich jedoch keine Sorgen, dass Sie möglicherweise 3-4 Mal auf die Schaltfläche "Weiter" klicken müssen, um die Anwendung auszuführen.
Vatsal K
Das ist in einem solchen Fall kein Fehler. Einige alte Frameworks verursachen diese Art von Problem. Versuchen Sie, Ihre alten Frameworks auf neue / aktualisierte zu aktualisieren. Das sollte das Problem lösen.
Vatsal K
30

Der kritische erste Schritt ist die Analyse der Fehlermeldung:

[UITableViewCellContentView image]: unrecognized selector sent to instance

Dies sagt Ihnen, dass die "Nachricht image" an ein Objekt der Klasse UITableViewCellContentView "gesendet" wurde. (Mit anderen Worten, es wurde versucht, die Methode imagefür ein Objekt der Klasse UITableViewCellContentView aufzurufen.)

Die erste Frage lautet: "Ist das überhaupt sinnvoll?" Es kann sein, dass die benannte Klasse eine ImageMethode hat, aber keine imageMethode, und daher wurde beim Aufruf der falsche Methodenname verwendet. Oder es kann sein, dass die benannte Methode ist someMethod:someParm:, aber die Klasse implementiert someMethod:someParm:anotherParm:, was bedeutet, dass ein Parameter beim Aufruf weggelassen wurde.

Meistens hat die benannte Klasse jedoch keine Methode, die der benannten Methode auch nur vage ähnelt, was bedeutet, dass im fehlgeschlagenen Aufruf irgendwie ein Zeiger auf das falsche Objekt verwendet wurde.

Zum Beispiel könnte man tun:

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

Und erhalten Sie einen Fehler wie folgt:

[__NSDictionaryI objectAtIndex:] unrecognized selector sent to instance

weil das abgerufene Objekt myDictionarytatsächlich ein NSDictionary war, nicht das erwartete NSArray.

Am verwirrendsten ist leider, wenn diese Art von Fehler tief im UI-Systemcode und nicht in Ihrem eigenen Code auftritt. Dies kann passieren, wenn Sie irgendwie das falsche Objekt an eine Systemschnittstelle übergeben oder möglicherweise die falsche Klasse in Interface Builder oder wo auch immer konfiguriert haben.

Hot Licks
quelle
6

Ein weiterer möglicher Grund ist, dass das ursprüngliche Objekt zerstört wurde und dann ein anderes Objekt an derselben Speicheradresse zugewiesen wurde. Dann sendet Ihr Code die Nachricht und denkt, dass sie noch einen Zeiger auf das alte Objekt hat, und Objective-C löst eine Ausnahme aus, weil das neue Objekt diese Nachricht nicht versteht.

Führen Sie den Profiler mit der Erkennung "Zombies" aus, um dieses Problem zu diagnostizieren.

Bryan
quelle
2

Swift 5.0

Mit Introspection können Sie herausfinden, ob das Objekt auf einen bestimmten Selektor reagiert oder nicht.

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

Nur wenn es stimmt, funktioniert der Code. Andernfalls stürzt er mit Sicherheit ab

Saranjith
quelle
1

In diesen Szenarien fand ich es hilfreich, zwei Dinge zu betrachten

  1. Der Call-Stack
  2. Die lokalen Variablen (und ihre Typen) an jedem Stapelrahmen

Wenn dieser Fehler aufgetreten ist, habe ich normalerweise eine Nachricht an eine Instanz von Typ A gesendet, als ich Typ B erwartet hatte.

In diesem speziellen Szenario erfüllen Sie möglicherweise nicht die Anforderungen einer übergeordneten Klasse (da Ihre Instanz von ItemTableViewCell höchstwahrscheinlich erbt).

Können Sie uns vielleicht den Code für Ihre ItemTableViewCell-Klasse zeigen?

ABC
quelle
1

Sie können den folgenden Code verwenden, um die Variable zu deklarieren:

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
    }
}
Yogesh Shelke
quelle
0

Ich hatte das gleiche Problem und das hat bei mir funktioniert:

Überschreiben Sie die isEqual in Ihrer SKScene:

- (BOOL)isEqual:(id)other {

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

Sie müssen übergeben, indexPathum das Objekt der Tabellenansichtszelle zu deklarieren.

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

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

    return cell
}
Rohit Parsana
quelle