Die Verwendung von Swift 3 @objc Inferenz im Swift 4-Modus ist veraltet?

485

Kurz gesagt, während ich Xcode 9 Beta verwende, ist folgende Warnung aufgetreten:

Die Verwendung von Swift 3 @objc-Inferenz im Swift 4-Modus ist veraltet. Bitte adressieren Sie veraltete @ OBJC-Inferenzwarnungen, testen Sie Ihren Code mit aktivierter Protokollierung "Verwendung veralteter Swift 3 @ OBJC-Inferenz" und deaktivieren Sie Swift 3 @ OBJC-Inferenz. **

Nach einigen Recherchen habe ich immer noch keine Ahnung, wie ich das Problem beheben kann. Ich würde mich über Tipps zur Behebung dieses Problems sowie über eine Erklärung der Vorgänge sehr freuen.

Mein Ziel ist es, ein besseres Verständnis dafür zu erlangen, was mit meinem Code passiert.

DaleK
quelle
4
Ich bekomme nicht wirklich eine Warnmeldung, welches Objekt es verursacht. Xcode sagt einfach nicht, in welcher Zeile sich das Objekt befindet. Irgendwelche Ratschläge, wie Sie herausfinden können, woher diese Warnung kommt?
Olyv

Antworten:

816

Ich habe diese Warnung beseitigt, indem ich die Build-Einstellung "Swift 3 @objc Inference" meiner Ziele auf "Standard" geändert habe.

Deaktivieren Sie die Swift 3 @objc-Inferenz in Xcode9

Aus diesem Artikel :

Vor Swift 4 stellte der Compiler Objective-C einige Swift-Deklarationen automatisch zur Verfügung . Wenn beispielsweise eine Unterklasse von NSObject erstellt wurde, hat der Compiler Objective-C-Einstiegspunkte für alle Methoden in solchen Klassen erstellt. Der Mechanismus heißt @objc Inferenz.

In Swift 4 ist eine solche automatische @ objc-Inferenz veraltet, da es teuer ist, alle diese Objective-C-Einstiegspunkte zu generieren. Wenn die Einstellung "Swift 3 @objc Inference" auf "On" gesetzt ist, kann der alte Code funktionieren. Es werden jedoch Verfallswarnungen angezeigt, die behoben werden müssen. Es wird empfohlen, diese Warnungen zu "korrigieren" und die Einstellung auf "Standard " zu setzen. Dies ist die Standardeinstellung für neue Swift-Projekte.

Weitere Informationen finden Sie auch in diesem Swift-Vorschlag .

Evgenii
quelle
5
Danke Evgenii. Ist das eine langfristige Lösung?
DaleK
6
@ DaleK ja, ich glaube schon. Gemäß dem Swift-Vorschlag, den ich in meiner Antwort erwähnt habe, ist die objc-Folgerung veraltet. Die Einstellung "Swift 3 objc Inference" ist nur in Projekten vorhanden, die von älteren Versionen von Swift migriert wurden. Wenn man ein neues Projekt erstellt, ist die Einstellung nicht mehr vorhanden, was bedeutet, dass die Objektinferenz deaktiviert ist. Es wird empfohlen, eventuelle Inferenzwarnungen zu beheben und auf "Aus" zu setzen.
Evgenii
4
In der Infomeldung in XCode heißt es: "Die Verwendung der Swift 3- @objcInferenz im Swift 4-Modus ist veraltet. Bitte beheben Sie veraltete @objcInferenzwarnungen, testen Sie Ihren Code mit @objcaktivierter Protokollierung " Verwendung veralteter Swift 3- Inferenz " und deaktivieren Sie die Swift 3- @objcInferenz." Haben Sie eine Idee, wo Sie die besagte Swift 3- @objcInferenzprotokollierung aktivieren können ?
Courteouselk
4
@courteouselk Gemäß dem Swift-Vorschlag kann die Umgebungsvariable SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT auf Werte von 1 bis 3 gesetzt werden, um die Verwendung der Objective-C-Einstiegspunkte in den Protokollen anzuzeigen.
Evgenii
14
Nur zum Hinzufügen - Sie müssen dies für alle Build-Tagets tun, nicht nur für das Projekt.
Krivvenz
270

- Was ist @objcFolgerung? Was ist los?

In Swift 3schließt der Compiler @objcan mehreren Stellen, sodass Sie dies nicht tun müssen. Mit anderen Worten, es stellt sicher, @objcfür Sie hinzuzufügen !

In macht Swift 4der Compiler dies nicht mehr (so viel). Sie müssen jetzt @objcexplizit hinzufügen .

Wenn Sie ein Projekt vor Swift 4 haben, erhalten Sie standardmäßig Warnungen dazu. In einem Swift 4-Projekt werden Buildfehler angezeigt. Dies wird über die SWIFT_SWIFT3_OBJC_INFERENCEBuild-Einstellung gesteuert . In einem Pre-Swift 4-Projekt ist dies auf eingestellt On. Ich würde empfehlen, dies auf Default(oder Off) zu setzen, was jetzt die Standardoption für ein neues Projekt ist.

Es wird einige Zeit dauern, bis alles konvertiert ist, aber da dies die Standardeinstellung für Swift 4 ist, lohnt es sich, dies zu tun.

- Wie stoppe ich die Compiler-Warnungen / Fehler?

Es gibt zwei Möglichkeiten, Ihren Code zu konvertieren, damit sich der Compiler nicht beschwert.

Eine Möglichkeit besteht darin, @objcfür jede Funktion oder Variable zu verwenden, die für die Objective-C-Laufzeit verfügbar gemacht werden muss:

@objc func foo() {

}

Die andere ist @objcMembersdurch eine ClassErklärung zu verwenden. Dies stellt sicher , automatisch hinzufügen , @objcum ALL die Funktionen und Variablen in der Klasse. Dies ist der einfache Weg, der jedoch Kosten verursacht. Beispielsweise kann er die Größe Ihrer Anwendung erhöhen, indem Funktionen verfügbar gemacht werden, die nicht verfügbar gemacht werden mussten.

@objcMembers class Test {

}

- Was ist @objcund warum ist es notwendig?

Wenn Sie einer Swift-Klasse neue Methoden oder Variablen hinzufügen, werden sie durch Markieren als @objcfür die Objective-C-Laufzeit verfügbar gemacht. Dies ist erforderlich, wenn Sie über Objective-C-Code verfügen, der Ihre Swift-Klasse verwendet, oder wenn Sie Funktionen vom Typ Objective-C wie verwenden Selectors. Zum Beispiel das Zielaktionsmuster: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Warum sollte ich nicht alles markieren @objc?

Es gibt Negative, die mit der Kennzeichnung von etwas verbunden sind als @objc:

  • Erhöhte Größe der Anwendungsbinärdatei
  • Keine Funktionsüberlastung

Bitte denken Sie daran, dass dies eine Zusammenfassung auf sehr hoher Ebene ist und dass sie komplizierter ist als ich geschrieben habe. Ich würde empfehlen, den aktuellen Vorschlag zu lesen, um weitere Informationen zu erhalten.

Quellen:

kgaidis
quelle
@objcDies bedeutet keinen dynamischen Versand. Swift kann den statischen oder virtuellen Versand verwenden (und möglicherweise einen anderen Code ausführen). Das dynamicSchlüsselwort ist erforderlich, um Swift zur Verwendung des dynamischen Versands zu zwingen.
Kevin
7
Gibt es andere Möglichkeiten, der Schaltfläche eine Aktion hinzuzufügen? Wenn @objcberaubt, was müssen wir verwenden?
Aznix
5
@Stefan ja, es kann einiges zu konvertieren geben. Teilen Sie es in Stufen auf. Lassen Sie SWIFT_SWIFT3_OBJC_INFERENCEbei On. Konvertieren Sie zu Swift 4. Dann packen Sie das @objcZeug an. Befolgen Sie zur Vereinfachung die folgenden Grundregeln: Wenn die Swift-Klasse im Objc-C-Code verwendet wird (über den Bridging-Header), verwenden Sie @objcMembersandernfalls das Add-by-One-Add @objc. Verwenden Sie einfach die Xcode-Suche, um herauszufinden, ob die Swift-Klasse aus einer beliebigen .mDatei aufgerufen wird. Dies sollte die Umwandlung relativ schmerzfrei machen.
kgaidis
5
@ DaleK dies sollte Antwort akzeptiert werden. Das Unterdrücken von Warnungen und das Funktionieren von Dingen wie in Swift 3 ist eine Option, aber meiner Meinung nach nicht die beste. Es ist wichtig zu verstehen, warum sich @objcSwift 4 geändert hat, und dann die Entscheidung zu treffen, das Projekt zu reparieren und es gleich zu halten.
derpoliuk
2
Vielen Dank für diese kurze Erklärung
Schmoudi
48

Migrator kann nicht alle Funktionen identifizieren, für die @objc Inferred Objective-C- Thunks erforderlich sind, die als veraltet markiert sind , damit Sie sie leichter finden können.
• Erstellen Sie Warnungen zu veralteten Methoden.
• Konsolenmeldungen beim Ausführen veralteter Thunks

Geben Sie hier die Bildbeschreibung ein

Hassan Taleb
quelle
1
Was soll ich also mit @objc machen? entfernen Sie es? Lass es? Das habe ich schon entfernt. und die ich habe diese Warnung bekommen, damit ich sie hinzufügen muss? dass ich in Schritt 3 damit anfangen soll?
Shial
Fügen Sie @objc kurz vor func hinzu
Hassan Taleb
1
Worum geht es in Schritt 3? Sie könnten einige Beschreibungen hinzufügen :)
Shial
In meinem Fall erhalte ich diese Warnung, aber es wird kein Code angezeigt. Es gibt zwei Methoden, die mit @objc gekennzeichnet sind, und sie scheinen die einzigen zu sein, die sie benötigen. Ich habe es in Standard geändert und erhalte immer noch die Warnungen beim Kompilieren.
Maury Markowitz
12

Ich hatte diese Warnung mit der Einstellung "Swift 3 @objc Inference" = "Default". Dann wurde mir klar, dass dies für das Projekt festgelegt wurde - nicht für das Ziel. Stellen Sie also sicher, dass Sie in Ihrem Ziel die Einstellung "Standard" haben, um die Warnung zu entfernen.

Dmitry
quelle
Ich habe 20 Minuten damit verbracht, den Fehler zu beheben, selbst nachdem ich in den Projekteinstellungen auf Standard geändert habe. Sie haben genau darauf hingewiesen, dass es auch im Ziel geändert werden muss.
SkrewEverything
8

Sie können einfach auf "Standard" anstatt auf "EIN" übergeben. Scheint mehr an der Apple-Logik festzuhalten.

(aber alle anderen Kommentare zur Verwendung von @objbleiben gültig.)

ingconti
quelle
7

In der Tat werden Sie diese Warnungen entfernen, indem Sie Swift 3 @objc Inference deaktivieren. Es können jedoch subtile Probleme auftreten. Zum Beispiel wird KVO nicht mehr funktionieren. Dieser Code funktionierte perfekt unter Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

Nach der Migration auf Swift 4 und der Standardeinstellung von "Swift 3 @objc Inference" funktionierten bestimmte Funktionen meines Projekts nicht mehr . Ich musste einige Fehler beheben und nachforschen, um eine Lösung dafür zu finden. Nach meinem besten Wissen sind hier die Optionen:

  • Aktivieren Sie "Swift 3 @objc Inference" (funktioniert nur, wenn Sie ein vorhandenes Projekt von Swift 3 migriert haben). Geben Sie hier die Bildbeschreibung ein
  • Markieren Sie die betroffenen Methoden und Eigenschaften als @objc Geben Sie hier die Bildbeschreibung ein
  • Aktivieren Sie die ObjC-Inferenz für die gesamte Klasse mithilfe von @objcMembers erneut Geben Sie hier die Bildbeschreibung ein

Wenn Sie die @ ojjc-Inferenz erneut aktivieren, erhalten Sie die Warnungen, aber dies ist die schnellste Lösung. Beachten Sie, dass es nur für Projekte verfügbar ist, die von einer früheren Swift-Version migriert wurden. Die beiden anderen Optionen sind langwieriger und erfordern einige Code-Grabungen und umfangreiche Tests.

Siehe auch https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md

Karoly Nyisztor
quelle
7

Ich bin ein gelegentlicher iOS-Entwickler (bald mehr), aber ich konnte die Einstellung immer noch nicht anhand der anderen Antwort finden (da ich diesen Schlüsselbund nicht hatte, den die Antwort zeigt), also dachte ich jetzt, da ich ihn gefunden hatte Ich könnte diesen Schnappschuss einfach mit den hervorgehobenen Stellen hinzufügen, auf die Sie klicken und suchen müssen.

  1. Beginnen Sie oben links
  2. Wählen Sie das Projektordnersymbol
  3. Wählen Sie Ihren Hauptprojektnamen unter dem Projektordnersymbol.
  4. Wählen Sie auf der rechten Seite Build-Einstellungen.
  5. Wählen Sie Ihr Projekt unter ZIELE.
  6. Scrollen Sie sehr weit nach unten (oder suchen Sie im Suchtextfeld nach der Wortinferenz)

Einstellung finden

Raddevus
quelle
6

Sie können versuchen, "Pod Update" und / oder "Flattern sauber"

Ich habe diese Einstellung auch in xcode eingestellt.

Die Einstellung für die Objective-C-Schnittstelle lautet wie folgt:

ObjectiveC-Schnittstelleneinstellung

Wisekiddo
quelle
2

Swift 3 @objc Inferenz Die Verwendung der Swift 3 @objc Inferenz im Swift 4-Modus ist veraltet. Bitte adressieren Sie veraltete @ OBJC-Inferenzwarnungen, testen Sie Ihren Code mit aktivierter Protokollierung "Verwendung veralteter Swift 3 @ OBJC-Inferenz" und deaktivieren Sie dann die Inferenz, indem Sie die Build-Einstellung "Swift 3 @ OBJC-Inferenz" für "XMLParsingURL" auf "Standard" ändern. Ziel.

kam zum

  1. Der erste Schritt war Build Setting

  2. Suchen Sie in, um Einstellungsinferenz zu erstellen

  3. change swift 3 @objc Inference Default

Geben Sie hier die Bildbeschreibung ein

Praveen Kumar
quelle
1

Alles, was Sie brauchen, ist nur ein Test, warten Sie bis zum Ende. Gehen Sie danach zu Build Setting, Search in Build Setting Inference und ändern Sie swift 3 @objc Inference in (Default). Das ist alles, was ich getan und perfekt gearbeitet habe.

Acasey
quelle
0

Die Verwendung von Swift 3 @objc Inferenz im Swift 4-Modus ist veraltet?

benutze func call @objc

func call(){

foo()

}

@objc func foo() {

}
Puji Wahono
quelle
0

Zusätzlich zu den Aussagen von @wisekiddo können Sie Ihre Build-Einstellungen in der project.pbxprojDatei ändern, indem Sie die Swift 3 @obj-Inferenz auf die Standardeinstellungen SWIFT_SWIFT3_OBJC_INFERENCE = Default;für Ihre Build- Varianten (z. B. Debug und Release) setzen, insbesondere wenn Sie aus einer anderen Umgebung stammen neben Xcode

DaveNOTDavid
quelle