L'uso dell'inferenza di Swift 3 @objc in modalità Swift 4 è obsoleto?


485

In breve, durante l'utilizzo di Xcode 9 Beta, ho riscontrato il seguente avviso:

L'uso dell'inferenza di Swift 3 @objc in modalità Swift 4 è obsoleto. Si prega di indirizzare gli avvisi di inferenza @objc obsoleti, testare il codice con la registrazione "Utilizzo di inferenza di Swift 3 obsoleta" abilitata e disabilitare l'inferenza di @iftjc Swift 3. **

Dopo alcune ricerche, non ho ancora idea di come risolvere il problema. Gradirei molto eventuali suggerimenti su come risolvere questo problema, nonché una spiegazione di ciò che sta succedendo.

Il mio obiettivo è capire meglio cosa sta succedendo con il mio codice.


4
In realtà non ricevo dal messaggio di avviso quale oggetto lo sta causando. Xcode semplicemente non dice in quale riga si trova l'oggetto. Qualche consiglio su come scoprire da dove proviene questo avviso?
olyv

Risposte:


816

Mi sono sbarazzato di questo avviso cambiando l'impostazione di build "Swift 3 @objc Inference" dei miei target su "Default".

Disabilita l'inferenza di Swift 3 @objc in Xcode9

Da questo articolo :

Prima di Swift 4, il compilatore rendeva automaticamente disponibili alcune dichiarazioni Swift per Objective-C . Ad esempio, se una sottoclasse da NSObject, il compilatore ha creato punti di ingresso Objective-C per tutti i metodi in tali classi. Il meccanismo si chiama inferenza @objc.

In Swift 4, tale inferenza automatica di @objc è obsoleta perché è costoso generare tutti quei punti di ingresso dell'obiettivo-C. Quando l'impostazione "Swift 3 @objc Inference" è impostata su "On", consente al vecchio codice di funzionare. Tuttavia, mostrerà avvisi di deprecazione che devono essere indirizzati. Si consiglia di "correggere" questi avvisi e cambiare l'impostazione su "Predefinito" , che è l'impostazione predefinita per i nuovi progetti Swift.

Per ulteriori informazioni, consultare anche questa proposta Swift .


5
Grazie Evgenii. È una soluzione a lungo termine?
DaleK,

6
@DaleK sì, credo di si. Secondo la proposta Swift che ho citato nella mia risposta, l'inferenza oggettiva è deprecata. L'impostazione "Swift 3 objc Inference" è presente solo nei progetti migrati da versioni precedenti di Swift. Se si crea un nuovo progetto, l'impostazione non è più presente, il che significa che l'inferenza objc è disattivata. Si consiglia di indirizzare tutti gli avvisi di inferenza objc e impostarlo su "Off".
Evgenii,

4
Il messaggio informativo in XCode suggerisce che: "L'uso @objcdell'inferenza di Swift 3 in modalità Swift 4 è deprecato. Si prega di indirizzare gli @objcavvisi di inferenza deprecata , testare il codice con la registrazione" Uso di @objcinferenza Swift 3 deprecata "abilitata e disabilitare l' @objcinferenza di Swift 3 ". Qualche idea su dove abilitare la @objcregistrazione dell'inferenza di Swift 3 ?
courteouselk,

4
@courteouselk, secondo la proposta Swift, è possibile impostare la variabile ambientale SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT su valori da 1 a 3 per vedere gli usi dei punti di entrata Objective-C nei registri.
Evgenii,

14
Solo per aggiungere: è necessario eseguire questa operazione per tutti i tag di compilazione, non solo per il progetto.
Krivvenz,

270

- Che cos'è l' @objcinferenza? Cosa sta succedendo?

In Swift 3, il compilatore viene distribuito @objcin diversi punti, quindi non dovresti farlo. In altre parole, si assicura di aggiungere @objcper te!

In Swift 4, il compilatore non lo fa più (tanto). Ora devi aggiungere @objcesplicitamente.

Per impostazione predefinita, se disponi di un progetto pre-Swift 4, riceverai avvisi a riguardo. In un progetto Swift 4, otterrai errori di compilazione. Questo è controllato tramite l' SWIFT_SWIFT3_OBJC_INFERENCEimpostazione di compilazione. In un progetto pre-Swift 4 questo è impostato su On. Consiglierei di impostare questo su Default(o Off), che ora è l'opzione predefinita su un nuovo progetto.

Ci vorrà del tempo per convertire tutto, ma poiché è l'impostazione predefinita per Swift 4, vale la pena farlo.

- Come posso interrompere gli avvisi / errori del compilatore?

Esistono due modi per convertire il codice in modo che il compilatore non si lamenta.

Uno è da utilizzare @objcsu ogni funzione o variabile che deve essere esposta al runtime di Objective-C:

@objc func foo() {

}

L'altro è usare @objcMembersuna Classdichiarazione. Questo si assicura di aggiungere automaticamente @objca TUTTE le funzioni e le variabili nella classe. Questo è un modo semplice, ma ha un costo, ad esempio, può aumentare le dimensioni della tua applicazione esponendo funzioni che non avevano bisogno di essere esposte.

@objcMembers class Test {

}

- Che cos'è @objce perché è necessario?

Se si introducono nuovi metodi o variabili in una classe Swift, contrassegnarli come @objcli espone al runtime Objective-C. Ciò è necessario quando si dispone di codice Objective-C che utilizza la classe Swift o, se si utilizzano funzionalità di tipo Objective-C come Selectors. Ad esempio, il modello di azione-obiettivo: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Perché non dovrei segnare tutto @objc?

Ci sono aspetti negativi che derivano dalla marcatura di qualcosa come @objc:

  • Dimensione binaria dell'applicazione aumentata
  • Nessun sovraccarico di funzioni

Tieni presente che si tratta di un riepilogo di altissimo livello e che è più complicato di quanto ho scritto. Consiglierei di leggere la proposta attuale per ulteriori informazioni.

fonti:


@objcnon implica un invio dinamico, Swift è libero di utilizzare un invio statico o virtuale (e di conseguenza può eseguire codice diverso). La dynamicparola chiave è richiesta per forzare Swift a utilizzare l'invio dinamico.
Kevin

7
Esistono altri modi per aggiungere un'azione al pulsante? Se @objcdeprivato ciò che dobbiamo usare?
Aznix,

5
@Stefan sì, potrebbe esserci un bel po 'da convertire. Dividilo in più fasi. Lascia SWIFT_SWIFT3_OBJC_INFERENCEa On. Converti in Swift 4. Quindi affronta il problema @objc. Per semplificare, segui le regole di base: SE la classe Swift è utilizzata nel codice Objc-C (tramite intestazione a ponte), usa @objcMembers, altrimenti, l'aggiunta uno a uno @objc. Usa semplicemente la ricerca Xcode per scoprire se la classe Swift viene chiamata da qualsiasi .mfile. Ciò dovrebbe rendere la conversione relativamente indolore.
kgaidis,

5
@DaleK questa dovrebbe essere una risposta accettata. Sopprimere gli avvisi e far funzionare le cose come in Swift 3 è un'opzione, ma IMHO non è la migliore. È importante capire perché è @objccambiato in Swift 4 e quindi prendere una decisione per sistemare il progetto e mantenerlo lo stesso.
derpoliuk,

2
Grazie per questa breve spiegazione
Schmoudi,

48

Migrator non può identificare tutte le funzioni che devono @objc derivato Objective-C thunk contrassegnato come deprecato per aiutarti a trovare loro
• Costruire avvertimenti circa i metodi obsoleti
• Messaggi di console durante l'esecuzione thunk deprecato

inserisci qui la descrizione dell'immagine


1
Quindi cosa dovrei fare con @objc? rimuoverlo? lascialo? L'ho già rimosso. e ho ricevuto quegli avvisi quindi devo aggiungerli? che nel passaggio 3 dovrei fare con quello?
Shial,

Aggiungi @objc poco prima di func
Hassan Taleb il

1
di cosa si tratta al punto 3? Potresti aggiungere alcune descrizioni :)
Shial,

E nel mio caso, ricevo questo avviso, ma nessun codice è indicato. Esistono due metodi contrassegnati con @objc e sembrano gli unici che ne hanno bisogno. L'ho cambiato in Predefinito e continuo a ricevere gli avvisi durante la compilazione.
Maury Markowitz,

12

Ho ricevuto questo avviso con l'impostazione "Swift 3 @objc Inference" = "Default". Poi ho capito che era stato impostato per il Progetto, non per l'obiettivo. Quindi, assicurati di avere un'impostazione "Predefinita" nel tuo obiettivo per eliminare l'avviso.


Ho perso 20 minuti cercando di risolvere l'errore anche dopo essere passato a Predefinito nelle impostazioni del progetto. Hai indicato esattamente che deve essere cambiato anche nel target.
SkrewTutto il

8

Puoi semplicemente passare a "predefinito" invece di "ON". Sembra più aderente alla logica di Apple.

(ma tutti gli altri commenti sull'uso di @objrimangono validi.)


7

In effetti, ti sbarazzerai di quegli avvisi disabilitando Swift 3 @objc Inference. Tuttavia, possono apparire problemi sottili. Ad esempio, KVO smetterà di funzionare. Questo codice ha funzionato perfettamente con Swift 3:

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

Dopo la migrazione a Swift 4 e l'impostazione predefinita di "Swift 3 @objc Inference", alcune funzionalità del mio progetto hanno smesso di funzionare . Mi ci sono voluti un po 'di debug e ricerche per trovare una soluzione per questo. Secondo le mie migliori conoscenze, ecco le opzioni:

  • Abilita "Swift 3 @objc Inference" (funziona solo se hai migrato un progetto esistente da Swift 3) inserisci qui la descrizione dell'immagine
  • Contrassegna i metodi e le proprietà interessati come @objc inserisci qui la descrizione dell'immagine
  • Riattiva l'inferenza ObjC per l'intera classe usando @objcMembers inserisci qui la descrizione dell'immagine

La riattivazione dell'inferenza @objc ti lascia con gli avvisi, ma è la soluzione più rapida. Nota che è disponibile solo per i progetti migrati da una versione precedente di Swift. Le altre due opzioni sono più noiose e richiedono alcuni scavi di codice e test approfonditi.

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


7

Sono un occasionale sviluppatore iOS (presto lo sarà di più) ma non riesco ancora a trovare l'impostazione come guidato dall'altra risposta (poiché non avevo quell'elemento Keychain che mostra la risposta), quindi ora che l'ho trovato ho pensato Potrei semplicemente aggiungere questa istantanea con le posizioni evidenziate che dovrai cliccare e trovare.

  1. Inizia in alto a sinistra
  2. Scegli l'icona della cartella del progetto
  3. Scegli il nome del tuo progetto principale sotto l'icona della cartella del progetto.
  4. Scegli Impostazioni di costruzione sul lato destro.
  5. Scegli il tuo progetto in TARGETS.
  6. Scorri molto verso il basso (o cerca l'inferenza di parole nella casella di testo di ricerca)

Trovare l'impostazione


6

Puoi provare a "Aggiornamento pod" e / o "Flutter Clean"

Ho anche impostato questa impostazione in xcode.

L'impostazione dell'interfaccia Objective-C è la seguente:

Impostazione dell'interfaccia ObjectiveC


2

Inferenza di Swift 3 @objc L'uso di inferenza di Swift 3 @objc in modalità Swift 4 è obsoleto. Si prega di indirizzare gli avvisi di inferenza @objc obsoleti, testare il codice con la registrazione "Uso di Swift 3 @objc inferenza deprecata" abilitata, quindi disabilitare l'inferenza modificando l'impostazione di build "Swift 3 @objc Inference" su "Default" per "XMLParsingURL" bersaglio.

arrivato al

  1. Il primo passo è stato Build Setting

  2. Cerca per creare l'inferenza di impostazione

  3. change swift 3 @objc Inference Predefinito

inserisci qui la descrizione dell'immagine


1

Tutto ciò di cui hai bisogno è solo eseguire un test, attendere fino al termine, dopodiché vai a Build Setting, Cerca in Build Setting Inference, modifica swift 3 @objc Inference su (Default). è tutto ciò che ho fatto e funzionato perfettamente.


0

L'uso dell'inferenza di Swift 3 @objc in modalità Swift 4 è obsoleto?

usa func call @objc

func call(){

foo()

}

@objc func foo() {

}

0

Oltre a ciò che ha detto @wisekiddo, puoi anche modificare le impostazioni di compilazione nel project.pbxprojfile impostando Swift 3 @obj Inference su default come SWIFT_SWIFT3_OBJC_INFERENCE = Default;per i tuoi build build (es. Debug e release), specialmente se provieni da un altro ambiente oltre a Xcode

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.