Ich bin noch ein bisschen neu in Objective-C und frage mich, was der Unterschied zwischen den folgenden beiden Aussagen ist.
[object performSelector:@selector(doSomething)];
[object doSomething];
objective-c
selector
dynamic-languages
method-dispatch
Der Spieler
quelle
quelle
performSelector:
ist etwas, das Sie wahrscheinlich nur tun, wenn Sie eine Zielaktion in Ihrer Klasse implementieren. Die GeschwisterperformSelectorInBackground:withObject:
undperformSelectorOnMainThread:withObject:waitUntilDone:
sind oft nützlicher. Zum Laichen eines Hintergrundthreads und zum Zurückrufen von Ergebnissen aus diesem Hintergrundthread an den Hauptthread.performSelector
ist auch nützlich, um Kompilierungswarnungen zu unterdrücken. Wenn Sie wissen, dass die Methode vorhanden ist (wie nach der VerwendungrespondsToSelector
), wird Xcode daran gehindert, "möglicherweise nicht zu antwortenyour_selector
" zu sagen . Verwenden Sie es einfach nicht, anstatt die wahre Ursache der Warnung herauszufinden. ;)Für dieses sehr grundlegende Beispiel in der Frage,
Es gibt keinen Unterschied, was passieren wird. doSomething wird vom Objekt synchron ausgeführt. Nur "doSomething" ist eine sehr einfache Methode, die nichts zurückgibt und keine Parameter benötigt.
Wäre es etwas komplizierter, wie:
Dinge würden kompliziert werden, weil [object doSomethingWithMyAge: 42];
kann mit keiner Variante von "performSelector" mehr aufgerufen werden, da alle Varianten mit Parametern nur Objektparameter akzeptieren.
Der Selektor hier wäre "doSomethingWithMyAge:", aber jeder Versuch dazu
wird einfach nicht kompiliert. Das Übergeben einer NSNumber: @ (42) anstelle von 42 würde ebenfalls nicht helfen, da die Methode einen grundlegenden C-Typ erwartet - kein Objekt.
Darüber hinaus gibt es performSelector-Varianten mit bis zu 2 Parametern, nicht mehr. Während Methoden oft viel mehr Parameter haben.
Ich habe herausgefunden, dass obwohl synchrone Varianten von performSelector:
Immer ein Objekt zurückgeben, ich konnte auch ein einfaches BOOL oder NSUInteger zurückgeben, und es hat funktioniert.
Eine der beiden Hauptanwendungen von performSelector besteht darin, den Namen der Methode, die Sie ausführen möchten, dynamisch zusammenzustellen, wie in einer vorherigen Antwort erläutert. Beispielsweise
Die andere Verwendung besteht darin, eine Nachricht asynchron an ein Objekt zu senden, das später im aktuellen Runloop ausgeführt wird. Hierfür gibt es mehrere andere performSelector-Varianten.
(Ja, ich habe sie aus verschiedenen Foundation-Klassenkategorien wie NSThread, NSRunLoop und NSObject gesammelt.)
Jede der Varianten hat ihr eigenes spezielles Verhalten, aber alle haben etwas gemeinsam (zumindest wenn waitUntilDone auf NO gesetzt ist). Der Aufruf "performSelector" würde sofort zurückkehren und die Nachricht an das Objekt wird erst nach einiger Zeit in den aktuellen Runloop gestellt.
Aufgrund der verzögerten Ausführung ist natürlich kein Rückgabewert für die Methode des Selektors verfügbar, daher der Rückgabewert - (void) in all diesen asynchronen Varianten.
Ich hoffe ich habe das irgendwie abgedeckt ...
quelle
@ennuikiller ist genau richtig. Grundsätzlich sind dynamisch generierte Selektoren nützlich, wenn Sie den Namen der Methode, die Sie beim Kompilieren des Codes aufrufen, nicht kennen (und normalerweise auch nicht kennen können).
Ein wesentlicher Unterschied besteht darin, dass
-performSelector:
Freunde (einschließlich der Multithread- und verzögerten Varianten ) etwas eingeschränkt sind, da sie für die Verwendung mit Methoden mit 0-2-Parametern ausgelegt sind. Das Aufrufen-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:
mit 6 Parametern und das Zurückgeben vonNSString
ist beispielsweise ziemlich unhandlich und wird von den bereitgestellten Methoden nicht unterstützt.quelle
NSInvocation
Objekt verwenden.performSelector:
und Freunde nehmen alle Objektargumente, was bedeutet, dass Sie sie nicht zum Aufrufen verwenden können (zum Beispiel)setAlphaValue:
, da das Argument ein Float ist.Selektoren sind ein bisschen wie Funktionszeiger in anderen Sprachen. Sie verwenden sie, wenn Sie zur Kompilierungszeit nicht wissen, welche Methode Sie zur Laufzeit aufrufen möchten. Ebenso wie Funktionszeiger kapseln sie nur den Verbteil des Aufrufs. Wenn die Methode Parameter enthält, müssen Sie diese ebenfalls übergeben.
Ein
NSInvocation
dient einem ähnlichen Zweck, außer dass es mehr Informationen zusammenhält. Es enthält nicht nur den Verbteil, sondern auch das Zielobjekt und die Parameter. Dies ist nützlich, wenn Sie eine Methode für ein bestimmtes Objekt mit bestimmten Parametern nicht jetzt, sondern in Zukunft aufrufen möchten. Sie können ein geeignetes erstellenNSInvocation
und es später abfeuern.quelle
Es gibt einen weiteren subtilen Unterschied zwischen den beiden.
Hier ist der Auszug aus der Apple-Dokumentation
"performSelector: withObject: afterDelay: Führt den angegebenen Selektor für den aktuellen Thread während des nächsten Run-Loop-Zyklus und nach einer optionalen Verzögerungszeit aus. Da er bis zum nächsten Run-Loop-Zyklus wartet, um den Selector auszuführen, bieten diese Methoden eine automatische Mini-Verzögerung von Der aktuell ausgeführte Code. Mehrere Selektoren in der Warteschlange werden nacheinander in der Reihenfolge ausgeführt, in der sie in die Warteschlange gestellt wurden. "
quelle
performSelector:withObject:afterDelay:
, aber die Frage und Ihr Snippet verwendenperformSelector:
eine völlig andere Methode. Aus den Dokumenten dafür: <quote> DieperformSelector:
Methode entspricht dem Senden eineraSelector
Nachricht direkt an den Empfänger. </performSelector/performSelector:withObject/performSelector:withObject:afterDelay
alle verhalten sich gleich, was ein Fehler war.