Ich versuche, den Quellcode meines Projekts von Swift 3 in Swift 4 zu konvertieren. Eine Warnung, die Xcode mir gibt, betrifft meine Selektoren.
Zum Beispiel füge ich einer Schaltfläche ein Ziel hinzu, indem ich einen regulären Selektor wie folgt verwende:
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
Dies ist die Warnung, die angezeigt wird:
Das Argument von '#selector' bezieht sich auf die Instanzmethode 'myAction ()' in 'ViewController', die von der in Swift 4 veralteten Inferenz des Attributs '@objc' abhängt
Fügen Sie '@objc' hinzu, um diese Instanzmethode für Objective-C verfügbar zu machen
Wenn Sie nun Fix
auf die Fehlermeldung klicken, geschieht dies für meine Funktion:
// before
func myAction() { /* ... */ }
// after
@objc func myAction() { /* ... */ }
Ich möchte nicht wirklich alle meine Funktionen umbenennen, um die @objc
Marke einzuschließen, und ich gehe davon aus, dass dies nicht erforderlich ist.
Wie schreibe ich den Selektor neu, um mit der Abwertung umzugehen?
Verwandte Frage:
@objc
ist nun erforderlich, um sie zu Obj-C, zu belichten und damit mit Selektoren zu verwenden.@objc
? Das ist ein bisschen nervig, aber ich mache diese Funktionen im Allgemeinen privat und muss sie@objc
sowieso als markieren.@objcMembers
, um alle Obj-C-kompatiblen Mitglieder Obj-C auszusetzen. Ich würde dies jedoch nicht empfehlen, es sei denn, Sie benötigen tatsächlich die Bereitstellung Ihrer gesamten Klasse.Antworten:
Das Fix-it ist korrekt - es gibt nichts an dem Selektor, das Sie ändern können, um die Methode, auf die es sich bezieht, für Objective-C verfügbar zu machen.
Der ganze Grund für diese Warnung ist in erster Linie das Ergebnis von SE-0160 . Vor Swift 4
internal
oder höher wurde davon ausgegangen , dass Objective-C-kompatible MitgliederNSObject
erbender Klassen@objc
Objective-C ausgesetzt waren und daher mit Selektoren aufgerufen werden konnten (da die Obj-C-Laufzeit erforderlich ist, um die Methode nachzuschlagen Implementierung für einen bestimmten Selektor).In Swift 4 ist dies jedoch nicht mehr der Fall. Es wird nur noch auf sehr spezifische Erklärungen geschlossen
@objc
, dass sie beispielsweise@objc
Methodenüberschreibungen, Implementierungen von@objc
Protokollanforderungen und Deklarationen mit impliziten Attributen@objc
wie z@IBOutlet
.Die Motivation dahinter, wie im oben verlinkten Vorschlag dargelegt , besteht zunächst darin, zu verhindern, dass Methodenüberladungen beim
NSObject
Erben von Klassen aufgrund identischer Selektoren miteinander kollidieren. Zweitens hilft es, die Binärgröße zu reduzieren, indem keine Thunks für Mitglieder generiert werden müssen, die nicht Obj-C ausgesetzt sein müssen, und drittens wird die Geschwindigkeit der dynamischen Verknüpfung verbessert.Wenn Sie ein Mitglied Obj-C aussetzen möchten, müssen Sie es wie folgt markieren
@objc
:(Der Migrator sollte dies automatisch für Sie mit Selektoren tun, wenn die Option "Inferenz minimieren" ausgeführt wird.)
Um eine Gruppe von Mitgliedern Obj-C auszusetzen, können Sie Folgendes verwenden
@objc extension
:Dadurch werden alle darin definierten Mitglieder Obj-C ausgesetzt und es wird ein Fehler für alle Mitglieder ausgegeben, die Obj-C nicht ausgesetzt werden können (es sei denn, dies ist ausdrücklich als gekennzeichnet
@nonobjc
).Wenn Sie eine Klasse haben, in der alle Obj-C-kompatiblen Mitglieder für Obj-C verfügbar sein müssen, können Sie die Klasse wie folgt markieren
@objcMembers
:Nun werden alle Mitglieder, auf die man schließen kann
@objc
, sein. Ich würde jedoch nicht raten, dies zu tun, es sei denn, Sie benötigen wirklich alle Mitglieder, die Obj-C ausgesetzt sind, angesichts der oben genannten Nachteile, wenn Mitglieder unnötig ausgesetzt sind.quelle
@IBAction
auch automatisch@objc
? das war bisher nicht der Fall, aber es wäre logisch. EDIT: nvm, der Vorschlag besagt eindeutig, dass dies@IBAction
für eine Methode ausreicht@objc
.Als offizielle Dokumentation von Apple . Sie müssen @objc verwenden, um Ihre Auswahlmethode aufzurufen.
quelle
Ab Swift 4.2 müssen Sie Ihrer Methode lediglich @IBAction zuweisen, und Sie können diese dumme @ objc-Annotation vermeiden
`` `
quelle
Wie bereits in anderen Antworten erwähnt, gibt es keine Möglichkeit, das zu vermeiden
@objc
Anmerkung für Selektoren vermieden werden.Die im OP erwähnte Warnung kann jedoch durch die folgenden Schritte zum Schweigen gebracht werden:
Off
Unten sehen Sie den Screenshot, der die oben genannten Schritte veranschaulicht:
Hoffe das hilft
quelle
Wenn Sie Ziel-C-Mitglieder in Ihrem Ansichts-Controller benötigen, fügen Sie einfach @objcMembers oben im Ansichts-Controller hinzu. Und Sie können dies vermeiden, indem Sie IBAction in Ihren Code einfügen.
Stellen Sie sicher, dass diese Steckdose im Storyboard angeschlossen ist.
quelle