Fehler "Nicht erkannter Selektor an Instanz gesendet" in Objective-C


155

Ich habe eine Schaltfläche erstellt und eine Aktion hinzugefügt, aber sobald sie aufgerufen wurde, wurde folgende Fehlermeldung angezeigt:

-[NSCFDictionary numberButtonClick:]: unrecognized selector sent to instance
 0x3d03ac0 2010-03-16 22:23:58.811
 Money[8056:207] *** Terminating app
 due to uncaught exception
 'NSInvalidArgumentException', reason:'*** -[NSCFDictionary numberButtonClick:]:  unrecognized selector sent to instance 0x3d03ac0'

Das ist mein Code:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        UIButton *numberButton = [UIButton buttonWithType:UIButtonTypeCustom];        
        numberButton.frame = CGRectMake(10, 435, 46, 38);
        [numberButton setImage:[UIImage imageNamed:@"one.png"] forState:UIControlStateNormal];
        [numberButton addTarget:self action:@selector(numberButtonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview: numberButton]; 
    }
return self;
}

-(IBAction)numberButtonClick:(id)sender{
    NSLog(@"---");
}

Antworten:


187

Es sieht so aus, als ob Sie den View Controller nicht richtig verwalten und er irgendwann freigegeben wird - was dazu führt, dass numberButtonClicked: Methode an ein anderes Objekt gesendet, das jetzt den Speicher belegt, den der Ansichtscontroller zuvor belegt hat.

Stellen Sie sicher, dass Sie Ihren View Controller ordnungsgemäß beibehalten / freigeben.


105
Das ist eine sehr kluge Diagnose aus wenigen Codezeilen.
Michael Morrison

41
OK, das Problem wurde erkannt ... aber "Stellen Sie sicher, dass Sie Ihren View Controller ordnungsgemäß beibehalten / freigeben." ist ein Vorschlag, keine Lösung.
Alex Gray

12
@alex grau, was? Die richtige Speicherverwaltung auf dem View Controller hat das Problem gelöst ... Ich verstehe nicht, dass dies keine Lösung ist.
Jasarien

28
richtig. Dies scheint zwar "die Lösung" zu sein .. und ich bin vielleicht in der Minderheit (obwohl ich es immer noch schaffe zu existieren), aber der Zusammenhang zwischen dem Problem und der Lösung ist nicht sofort offensichtlich. Zum Beispiel begegne ich -[NSWindow end]: unrecognized selector sent to instance 0x100523e80 und obwohl ich die Ähnlichkeiten mit dem OP und möglicherweise sogar die Ursache des Problems aus Ihrer Antwort erkenne, ist die Implementierung eines Fixes nicht sofort offensichtlich
Alex Gray

12
Es ist sofort offensichtlich. Ihre NSWindow-Speicherverwaltung ist irgendwo auf der Linie nicht korrekt. Gehen Sie den Lebenszyklus durch und korrigieren Sie ihn.
Jasarien

127

Für diejenigen, die wie ich über Google hierher kommen, was wahrscheinlich mehr mit Xcode 4.2 + / iOS 5+ zu tun hat, was mit ARC. Ich hatte den gleichen Fehler " nicht erkannter Selektor an Instanz gesendet ". In meinem Fall hatte ich die Zielaktion eines UIButton eingerichtet, um sich selbst als Absenderparameter zu übergeben, aber später wurde mir klar, dass ich sie nicht brauchte, und ich entfernte sie im Code. Also so etwas wie:

- (IBAction)buttonPressed:(UIButton *)sender {

Wurde geändert in:

- (IBAction)buttonPressed {

Wenn Sie mit der rechten Maustaste auf den betreffenden UIButton klicken, wurde angezeigt, dass das Ereignis "Touch Up Inside" mit der Schaltfläche "Pressed:" der Ansichtssteuerung verknüpft war. Das Entfernen und Neuzuweisen zu der modifizierten Methode war ein Vergnügen.


Dies war sehr hilfreich, obwohl ich denke, dass seine eigene Frage und Antwort das Auffinden erleichtern würde.
Curtis Inderwiesche

@LeonardChallis Wie können Sie den Absender in buttonPressed referenzieren, wenn er nicht als Parameter übergeben wird?
Zakdances

8
Sehr hilfreiche Antwort. Ich bin gerade auf genau dieses Problem gestoßen und Ihre Lösung war genau richtig. Verfolgte die Stanford iOS-Klasse auf iTunesU, als dies passierte. Nochmals vielen Dank für Ihre Antwort!
Marshall Alsup

1
@ LeonardChallis Danke. Ich habe Ihrer Antwort eine kostenlose Antwort hinzugefügt.
1,21 Gigawatt

1
Ich hatte gerade mit einem ähnlichen Problem zu kämpfen, entfernte den Absenderparameter aus der Auswahlfunktion und fragte mich dann, wie ich den Absender bekommen sollte. In meinem Fall wurde der Fehler angezeigt, weil ich vergessen habe, nach dem Selektorrückruf einen Doppelpunkt einzufügen, was zu einer Nichtübereinstimmung der Aufrufsequenz führte. Mit dem Doppelpunkt kann ich das Absenderargument beibehalten.

74

Dies war die beste Google-Antwort für dieses Problem, aber ich hatte eine andere Ursache / ein anderes Ergebnis - ich dachte, ich würde meine zwei Cent hinzufügen, falls andere über dieses Problem stolpern.

Ich hatte gerade heute Morgen ein ähnliches Problem. Ich habe festgestellt, dass Sie sehen können, welche Verbindungen erstellt wurden, wenn Sie mit der rechten Maustaste auf das UI-Element klicken, das Ihnen das Problem gibt. In meinem Fall hatte ich einen Knopf mit bis zu zwei Aktionen. Ich habe die Aktionen aus dem Kontextmenü gelöscht und neu verkabelt, und mein Problem wurde behoben.

Stellen Sie also sicher, dass Ihre Aktionen richtig verkabelt sind.


Das war mein Problem. Ich habe eine Funktion umbenannt und meinen Code geändert, aber die Verbindung in der xib-Datei nicht geändert.
BFTrick

2
DANKE! Es stellte sich heraus, dass ich drei Methoden hatte, auf die ich noch verwiesen hatte. Mich eine Woche lang belästigen!
Erdekhayser

25

OK, ich muss hier rein. Das OP hat die Schaltfläche dynamisch erstellt . Ich hatte ein ähnliches Problem und die Antwort (nach stundenlanger Jagd) ist so einfach, dass ich krank wurde.

Beim Benutzen:

action:@selector(xxxButtonClick:)

or (as in my case)

action:NSSelectorFromString([[NSString alloc] initWithFormat:@"%@BtnTui:", name.lowercaseString])

Wenn Sie am Ende der Zeichenfolge einen Doppelpunkt platzieren, wird der Absender übergeben. Wenn Sie den Doppelpunkt nicht am Ende der Zeichenfolge platzieren, wird dies nicht der Fall sein, und der Empfänger erhält eine Fehlermeldung, wenn er eine erwartet. Es ist leicht, den Doppelpunkt zu übersehen, wenn Sie den Ereignisnamen dynamisch erstellen.

Die Empfängercode-Optionen sehen folgendermaßen aus:

- (void)doneBtnTui:(id)sender {
  NSLog(@"Done Button - with sender");
}
 or
- (void)doneBtnTui {
  NSLog(@"Done Button - no sender");
}

Wie immer ist es immer die offensichtliche Antwort, die übersehen wird.


1
Vielen Dank! Dies war mein Problem (kein Doppelpunkt ':' am Ende des Namens des Selektors). Wie kommt es, dass es fast immer die dümmsten einfachen Dinge sind, bei denen wir Geeks um 3 Uhr morgens mit dem Kopf gegen die Wand schlagen? Wirklich danke dir!
TWright

23

In meinem Fall hat die Funktion kein Argument erwartet, aber die Schaltfläche wurde so konfiguriert, dass eines gesendet wird, das den Fehler verursacht. Um dies zu beheben, musste ich den Event-Handler neu verkabeln.

Hier ist meine Funktion:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass es keine Argumente enthält.

Hier ist ein Bild meiner Schaltflächenkonfiguration (klicken Sie mit der rechten Maustaste auf die Schaltfläche, um sie anzuzeigen):

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass es 3 Ereignishandler gibt.

Um dies zu beheben, musste ich jedes Ereigniselement entfernen, da eines von ihnen einen Verweis auf die enterPressed-Funktion an sich selbst sendete. Um diese Elemente zu entfernen, klickte ich auf das kleine x-Symbol neben dem Namen jedes Elements, bis keine Elemente mehr angezeigt wurden.

Geben Sie hier die Bildbeschreibung ein

Als nächstes musste ich den Button wieder mit dem Event verbinden. Halten Sie dazu die Strg-Taste gedrückt und ziehen Sie eine Linie von der Schaltfläche zur Aktion. Es sollte "Connect Action" stehen. Hinweis: Ich musste XCode neu starten, damit dies aus irgendeinem Grund funktioniert. Andernfalls kann ich nur Aktionen (auch als neue Aktion erstellen) über oder unter der Funktion einfügen.

Geben Sie hier die Bildbeschreibung ein

Sie sollten jetzt einen einzelnen Ereignishandler mit dem Schaltflächenereignis verknüpfen, der keine Argumente übergibt:

Geben Sie hier die Bildbeschreibung ein

Diese Antwort ergänzt die Antwort von @Leonard Challis, die Sie ebenfalls lesen sollten.


14

Dies kann auch passieren, wenn Sie die "Klasse" der Ansicht im Interface Builder nicht festlegen.


Agh danke! Dies führte dazu, dass meine App in einem Abschnitt abstürzte. Ich habe nur vergessen, die Klasse des Controllers festzulegen.
Eichhörnchen

Warum muss es die Klasse kennen? Ich versuche, einen UITableViewSection als UIView zu verwenden, und daher wird dieser Fehler angezeigt. Der Compiler sagt, dass UITableViewSection nicht existiert, also nehme ich an, dass es UIKit-intern ist.
Ian Warburton

13

In meinem Fall habe ich NSNotificationCenter verwendet und versucht, einen Selektor zu verwenden, der keine Argumente akzeptiert, aber einen Doppelpunkt hinzufügt. Das Entfernen des Doppelpunkts hat das Problem behoben.

Verwenden Sie bei Verwendung eines Selektornamens keinen abschließenden Doppelpunkt, wenn keine Argumente vorhanden sind. Wenn es ein Argument gibt, verwenden Sie einen abschließenden Doppelpunkt. Wenn es mehr als ein Argument gibt, müssen Sie diese zusammen mit einem abschließenden Doppelpunkt für jedes Argument benennen.

Siehe Adam Rosenfields Antwort hier: Selektoren in Objective-C?


11

Ich hatte dieses Problem mit einem Swift-Projekt, bei dem ich die Schaltflächen dynamisch erstelle. Problemcode:

var trashBarButtonItem: UIBarButtonItem {
    return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked")
}

func newButtonClicked(barButtonItem: UIBarButtonItem) {
    NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
}

Die Lösung bestand darin, nach der Aktion einen vollständigen Doppelpunkt ':' hinzuzufügen: z

var trashBarButtonItem: UIBarButtonItem {
        return UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "newButtonClicked:")
    }

    func newButtonClicked(barButtonItem: UIBarButtonItem) {
        NSLog("A bar button item on the default toolbar was clicked: \(barButtonItem).")
    }

Vollständiges Beispiel hier: https://developer.apple.com/library/content/samplecode/UICatalog/Listings/Swift_UIKitCatalog_DefaultToolbarViewController_swift.html


Kurz nachdem ich dem Tutorial
gefolgt

6

Die offensichtlichste Ursache dafür (der Vollständigkeit halber enthalten) ist das falsche Wirken eines Zeigers und das Aufrufen einer Methode der falschen Klasse.

NSArray* array = [[NSArray alloc] init];
[(NSDictionary*)array objectForKey: key]; // array is not a dictionary, hence exception

Dies ist ein guter Hinweis - eine Unterklasse einer Ansicht oder eines Datenobjekts nicht zu unterteilen (z. B. indem kein Unterklassenname hinzugefügt wird) ist eine andere Möglichkeit, dies
Brad M

4

Ich hatte auch das gleiche Problem.

Ich habe meinen Uibutton in meinem Storyboard gelöscht und neu erstellt. Jetzt funktioniert alles einwandfrei.


3

Ich hatte ein ähnliches Problem, aber für mich war die Lösung etwas anders. In meinem Fall habe ich eine Kategorie verwendet, um eine vorhandene Klasse zu erweitern (UIImage für einige Größenänderungsfunktionen - siehe diese Anleitung, falls Sie interessiert sind) und vergessen, die * .m-Datei zum Build-Ziel hinzuzufügen. Dummer Fehler, aber nicht immer offensichtlich, wenn es darum geht, wo man suchen muss. Ich dachte, es lohnt sich zu teilen ...


3

Dies geschah mit meinem, weil versehentlich die "@IBAction-Funktion ..." in meinem UIViewcontroller-Klassencode gelöscht wurde, sodass im Storyboard das Referenz-Outlet erstellt wurde, aber zur Laufzeit gab es eine Funktion, um es zu verarbeiten.

Die Lösung bestand darin, die Outlet-Referenz im Eigenschafteninspektor zu löschen und sie dann neu zu erstellen, indem Sie sie mit der Befehlstaste in den Klassencode ziehen.

Ich hoffe es hilft!


Ebenso passierte mir dies auch, als die Schaltfläche auf eine Funktion verwies, die nicht mehr existierte.
Josh Wolff

2

Ich denke, Sie sollten die Leere anstelle der IBAction als Rückgabetyp verwenden. weil Sie eine Schaltfläche programmgesteuert definiert haben.


2

Eine andere mögliche Lösung: Fügen Sie Ihren Linker-Argumenten '-ObjC' hinzu.

Die vollständige Erklärung finden Sie hier: Objective-C-Kategorien in der statischen Bibliothek

Ich denke, das Wesentliche ist: Wenn die Kategorie in einer Bibliothek definiert ist, mit der Sie statisch verknüpfen, ist der Linker nicht intelligent genug, um Kategoriemethoden zu verknüpfen. Mit dem obigen Flag wird der Linker in allen objektiven C-Klassen und Kategorien verknüpft, nicht nur in denjenigen, von denen er glaubt , dass sie auf der Analyse Ihrer Quelle basieren müssen. (Bitte zögern Sie nicht, diese Antwort zu stimmen oder zu korrigieren. Ich kenne mich mit verknüpften Sprachen aus, also mache ich hier nur Papageien).


2

Ich hatte den gleichen Fehler und entdeckte Folgendes:

Wenn Sie den Code verwenden

[self.refreshControl addTarget:self action:@selector(yourRefreshMethod:) forControlEvents:UIControlEventValueChanged];

Sie denken vielleicht, es sucht nach dem Selektor:

- (void)yourRefreshMethod{
    (your code here)
}

Aber es sucht tatsächlich nach dem Selektor:

- (void)yourRefreshMethod:(id)sender{
    (your code here)
}

Dieser Selektor existiert nicht, so dass Sie den Absturz bekommen.

Sie können den Selektor so ändern, dass er den Absender (ID) empfängt, um den Fehler zu beheben.

Aber was ist, wenn Sie andere Funktionen haben, die die Aktualisierungsfunktion aufrufen, ohne einen Absender anzugeben? Sie benötigen eine Funktion, die für beide funktioniert. Eine einfache Lösung besteht darin, eine weitere Funktion hinzuzufügen:

- (void)yourRefreshMethodWithSender:(id)sender{
    [self yourRefreshMethod];
}

Ändern Sie anschließend den Pulldown-Code für die Aktualisierung, um stattdessen diesen Selektor aufzurufen:

[self.refreshControl addTarget:self action:@selector(yourRefreshMethodWithSender:) forControlEvents:UIControlEventValueChanged];

Ich mache auch den Stanford iOS-Kurs auf einem älteren Mac, der nicht auf die neueste Version von Mac OSX aktualisiert werden kann. Ich baue also immer noch für iOS 6.1 und dies hat das Problem für mich gelöst.


2

In meinem Fall habe ich das Problem nach 2 Stunden gelöst:

Der Absender (ein tabBar-Element) hatte kein Referenzierungs-Outlet . Es zeigte also nirgendwo hin.

Juste erstellt einen Referenzierungsausgang , der Ihrer Funktion entspricht.

Hoffe das könnte euch helfen.


Nur um hinzuzufügen, in meinem Fall habe ich vergessen, eine IBActionnach Swift zu portieren . Es wurde also beschwert, dass es diese Funktion aufrufen wollte, aber sie konnte nicht gefunden werden.
DevNebulae

1

Ich lerne gerade die iOS-Entwicklung und gehe das Buch "Beginning iOS6 Development" von aPress durch. Ich habe den gleichen Fehler in Kapitel 10: Storyboards erhalten.

Ich habe zwei Tage gebraucht, um es herauszufinden, aber herausgefunden, dass ich versehentlich das Tag der TableView-Zelle auf 1 gesetzt habe, wenn ich es nicht hätte tun sollen. Für alle anderen, die dieses Buch machen und einen ähnlichen Fehler erhalten, hoffe ich, dass dies hilft.

Ich hoffe wirklich, dass zukünftige Fehler in meinem Code leichter zu finden sind! hahaha. Der Debug-Fehler hat mich nicht in die richtige Richtung getrieben, um es herauszufinden (oder zumindest bin ich zu neu, um den Debugger zu verstehen, lol).


1

In meinem Fall habe ich eine UIWebView verwendet und im zweiten Parameter anstelle einer NSURL einen NSString übergeben. Ich vermute also, dass falsche Klassentypen, die an Funktionen übergeben werden, diesen Fehler verursachen können.


1

..Und jetzt meins

Ich hatte die Schaltfläche mit einer Methode verknüpft, die auf den Parameter einer anderen Schaltfläche zugegriffen hat, und das funktionierte hervorragend, ABER sobald ich versuchte, etwas mit der Schaltfläche selbst zu tun, bekam ich einen Absturz. Beim Kompilieren wurde kein Fehler angezeigt. Lösung?

Ich konnte die Schaltfläche nicht mit dem Eigentümer der Datei verknüpfen. Also, wenn jemand hier so dumm ist wie ich, versuch das :)


1

Noch eine etwas andere Lösung / Fall.

Ich verwende Xamarin und MvvmCross und habe versucht, den UIButton an ein ViewModel zu binden. Ich hatte den UIButton mit einem Outlet und einem TouchUpInside verbunden.

Beim Binden benutze ich nur das Outlet:

set.Bind (somethingOutlet).For ("TouchUpInside").To(vm => vm.Something);

Alles, was ich tun musste, war die Aktionsverbindung (TouchUpInside) in XCode zu entfernen, und das löste sie.

PS Ich denke, das hängt in seiner Basis alles mit den vorherigen Antworten und insbesondere mit @Chris Kaminski zusammen, aber ich hoffe, das hilft jemandem ...

Prost.


1

Ich hatte das gleiche Problem. Das Problem für mich war, dass eine Schaltfläche zwei Aktionsmethoden hatte. Ich habe eine erste Aktionsmethode für meine Schaltfläche erstellt und sie dann im Ansichts-Controller gelöscht, aber vergessen, die Verbindung im Haupt-Storyboard im Verbindungsinspektor zu trennen. Als ich eine zweite Aktionsmethode hinzufügte, gab es jetzt zwei Aktionsmethoden für eine Schaltfläche, die den Fehler verursachten.


1

Für mich war es eine übrig gebliebene Verbindung, die im Interfacebuilder Bij Ctrl-Dragging erstellt wurde. Der Name der unterbrochenen Verbindung befand sich im Fehlerprotokoll

*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[NameOfYourApp.NameOfYourClass nameOfCorruptConnection:]:
unrecognized selector sent to instance 0x7f97a48bb000'

Ich hatte eine Aktion mit einer Schaltfläche verknüpft. Durch Drücken der Taste stürzte die App ab, da das Outlet in meinem Code nicht mehr vorhanden war. Die Suche nach dem Namen im Protokoll führte mich im Storyboard dazu. Löschte es und der Absturz war weg!


0

Ich antworte Leonard Challis, da ich ebenso wie der Benutzer "oli206" die Stanford iOS-Klasse C193P belegte.

"Beenden der App aufgrund einer nicht erfassten Ausnahme 'NSInvalidArgumentException', Grund:"

Das Problem war, dass ich die Schaltfläche "Enter" am Taschenrechner zweimal angeschlossen hatte und ein Freund darauf hinwies, dass eine Überprüfung der Schaltfläche im Storyboard ergab, dass sich 2 Einträge in den Attributen "Touch Up Inside" befanden, als ich mit der rechten Maustaste darauf klickte die "Enter" -Taste. Das Löschen eines der beiden "Gesendeten Ereignisse" "Gesendete Ereignisse" löste das Problem.

Dies zeigte, dass das Problem (für die C193P-Videoklasse in der Rechner-exemplarischen Vorgehensweise in Aufgabe 1) als 2 gesendete Ereignisse ausgelöst wurde, von denen eines die Ausnahme verursachte.


Ich hatte 3 Einträge wie. :)
1,21 Gigawatt

0

Dies kann passieren, wenn Sie den ViewController nicht der ViewControllerScene im InterfaceBuilder zuweisen. Der ViewController.m ist also mit keiner Szene verbunden.



0

Eine andere wirklich dumme Ursache dafür ist, dass der Selektor in der Schnittstelle (.h) definiert ist, aber nicht in der Implementierung (.m) (pe typo).


0

Ein weiterer Grund / eine weitere Lösung zur Liste. Dieser wird durch iOS6.0 (und / oder schlechte Programmierung) verursacht. In älteren Versionen stimmte der Selektor überein, wenn die Parametertypen übereinstimmten, aber in iOS 6.0 kam es zu Abstürzen im zuvor funktionierenden Code, bei denen der Name des Parameters nicht korrekt war.

Ich habe so etwas gemacht

[objectName methodName:@"somestring" lat:latValue lng:lngValue];

aber in der Definition (sowohl .h als auch .m) hatte ich

(viod) methodName:(NSString *) latitude:(double)latitude longitude:(double)longitude;

Dies funktionierte gut unter iOS5, aber nicht unter 6, selbst wenn genau derselbe Build auf verschiedenen Geräten bereitgestellt wurde.

Ich verstehe nicht, warum der Compiler mir das sowieso nicht sagen konnte - Problem gelöst.


0

Dies kann auch passieren, wenn Sie eine Eigenschaft von einem ControllerA auf eine öffentliche Eigenschaft innerhalb einer benutzerdefinierten ControllerB-Klasse festlegen möchten und die "Benutzerdefinierte Klasse" im Identitätsinspektor in Storyboards noch nicht festgelegt haben.


0

Mein Problem und meine Lösung waren anders und ich dachte, ich sollte es hier posten, damit zukünftige Leser ihren Kopf davor bewahren können, gegen die Wand zu schlagen.

Ich habe demselben UIVIewController unterschiedliche xib zugewiesen, und selbst nachdem ich überall gesucht hatte, konnte ich nicht finden, wie ich es korrigieren konnte. Dann habe ich mein AppDelegate überprüft, in dem ich angerufen habe, initWithNibNameund festgestellt, dass ich beim Kopieren des Codes den xib-Namen geändert habe, aber vergessen habe, die UIViewControllerKlasse zu ändern . Wenn also keine der Lösungen für Sie funktioniert, überprüfen Sie Ihre initWithNibNameMethode.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.