2014-06-06 26 views
15

Sto tentando di utilizzare le classi Swift nel mio codice Objective-C, tuttavia le mie classi Swift non sembrano apparire nell'intestazione generata. Di conseguenza, la mia build fallisce con "Uso dell'identificatore non dichiarato 'HelloWorld'".L'intestazione Swift to Objective-C non contiene classi Swift

Ho utilizzato i modelli per creare un progetto denominato TestApp.

Ho la seguente Costruire Impostazioni nel mio obiettivo:

  • Nome del prodotto: TestApp
  • prodotto Nome Modulo: TestAppModule
  • Definisce Modulo: Sì

la documentazione di Apple dice di usare #import <TestApp/TestAppModule-Swift.h> ma questo non funziona.

Invece, sto usando #import "TestAppModule-Swift.h" nel mio file ".m". Sembra trovare questo.

sono in grado di spostarsi su di essa, e sembra che questo ...

// Generated by Swift version 1.0 (swift-600.0.34.4.5) 

#if defined(__has_include) && __has_include(<swift/objc-prologue.h>) 
# include <swift/objc-prologue.h> 
#endif 

...etc... 

ma nessun classi definite in là.

Ho un file Swift nel progetto che assomiglia a questo ...

class HelloWorld {  
    func hello() { 
     println("hello world") 
    } 
} 

Perchè questo lavoro non utilizza il file di intestazione standard posizione #import <TestApp/TestAppModule-Swift.h>?

Come posso ottenere le mie classi rapide in tale file di intestazione, quindi non otterrò l'errore "identificatore non dichiarato"?

risposta

16

Ecco come ho ottenuto farlo funzionare. Si può vedere una risposta più larga scala here.

Modifica questo:

class HelloWorld {  
    func hello() { 
     println("hello world") 
    } 
} 

A:

@objc class HelloWorld { 

    class func newInstance() -> HelloWorld { 
     return HelloWorld() 
    } 

    func hello() { 
     println("hello world") 
    } 
} 

Poi, Nel file objC:

#import "TestApp-Swift.h" 

E chiama come this:

HelloWorld * helloWorld = [HelloWorld newInstance]; 
[helloWorld hello]; 
+0

Grazie! Ma modifica per favore la tua risposta ... "classe func newInstance()" – TJez

+0

Grazie per aver segnalato che @TroyJ - nessun avviso sul compilatore SO :) – Logan

+1

Aggiornamento: menzionare @echelon rispondi qui come commento alla risposta ufficiale, quindi che potrebbe aiutare qualcuno. Ho avuto tutto a posto.La parola chiave objc, la mia classe swift una sottoclasse di NSObject. Ancora non funzionava. Risulta, come menzionato da echelon nella sua risposta, che abbiamo bisogno di avere l'intestazione del bridging in atto, anche se non chiameremo obj-c nel codice Swift. Strano, ma ha funzionato. –

9

È opportuno utilizzare #import "TestAppModule-Swift.h" nei file .m. Se è necessario fare riferimento a una classe in un file .h, utilizzare la dichiarazione diretta @class.

Inoltre, se si desidera utilizzare una classe Swift da Objective-C, la classe Swift deve essere contrassegnata con l'attributo @objc. Xcode includerà solo le classi con quello attribuito nell'intestazione generata. Vedi anche this documentation.

+1

Grazie per aver ricordato l'annotazione @objc, ti ho dato un upvote. Avevo anche bisogno di estendere da NSObject o usare un nuovo metodo di classeInstance. Logan ha fornito una risposta completa e corretta con un esempio. – TJez

+0

Grazie mille! Aggiungi i file -Swift.h nella parte superiore dei miei file .m per risolvere il problema! –

+1

La documentazione afferma: "Se la tua classe Swift è discendente da una classe Objective-C, il compilatore aggiunge automaticamente l'attributo' @ objc' per te. " Tuttavia, con l'ultimo Xcode 7 questo sembra non essere più il caso (almeno per una sottoclasse 'UIViewController'). Ho dovuto aggiungere l'annotazione manualmente. – simeon

2

Un modo più comodo sarebbe ereditare da NSObject.In questo modo:

class HelloWorld: NSObject {  
    func hello() { 
     println("hello world") 
    } 
} 
14

tl; dr Assicurarsi di avere un colpo di testa colmare se si sta facendo qualsiasi cross-chiamate tra Objective-C e Swift.

ho avuto lo stesso identico problema: ho potuto vedere il file -Swift.h in DerivedData ma non ha fatto menzione delle mie classi Swift. Stavo importando correttamente il file header, l'impostazione Defines Module era YES e il Product Module Name era corretto. Ho provato a cancellare e riaggiungere i file Swift, pulire buiild, uscire da XCode, ecc, senza fortuna.

Poi ho capito che avevo alcun file -Bridging-header.h nel mio progetto, presumibilmente a causa del modo in cui avevo acciottolata insieme da un progetto precedente. Non dovrebbe essere un problema perché non stavo (ancora) chiamando Objective-C da Swift. Ma quando ho aggiunto un colpo di testa colmare, e di cui al suo percorso nelle impostazioni di generazione (Swift del compilatore - Generazione di codice -> Objective-C Bridging Header), magicamente risolto il problema - il mio file -Swift.h era improvvisamente pieno di SWIFT_CLASS () bontà!

Così sto cercando di indovinare l'intestazione ponte è fondamentale per il processo, anche se non siete usando Objective-C da Swift.


UPDATE: ho finalmente capito questo. È correlato a modificatori di accesso pubblico/interno. Non sono sicuro se ho perso questo in origine o se si tratta di un'aggiunta alla documentazione di Apple, ma ora afferma chiaramente: -

Per impostazione predefinita, l'intestazione generato contiene le interfacce per Swift dichiarazioni contrassegnati con il modificatore pubblico. Esso contiene anche quelli contrassegnati con il modificatore interna se l'obiettivo applicazione ha un header colmare Objective-C.

+0

L'intestazione del bridging non è stata creata nel mio caso anche quando ho creato un nuovo file Swift. Questo ha causato un problema quando volevo usare una classe Swift da una classe Objective C. Il problema è stato risolto aggiungendo manualmente un'intestazione di bridging. Grazie!! – vomako

7

classe deve essere dichiarato come @objc pubblico classe

+0

A meno che non si disponga di un'intestazione di collegamento. Vedi la mia risposta per la spiegazione. Il problema è che a volte le persone sottoclasse dal framework Cocoa senza contrassegnare esplicitamente la sottoclasse (e tutti i metodi sottoposti a override) come 'public' perché è meno digitante e funzionerà comunque felicemente con l'accesso' internal' predefinito. Ed è verosimilmente corretto, dal punto di vista OO. Questo causa quindi un problema quando vogliono esporre la classe a Objective-C e non hanno un'intestazione di bridging. – Echelon

0

Nel mio caso la classe non è stato in fase di compilazione, perché ho arricchiva solo il mio target di test ... Dopo aver aggiunto al mio principale target (Build Phases -> Compile Sources), è stato compilato e aggiunto al file di intestazione.

Questo per quanto riguarda TDD ;-)

0

Nel mio caso, seguendo le linee guida di Apple, non ha funzionato fino a quando mi sono imbattuto il progetto. L'editor xcode ha mantenuto la segnalazione della classe swift sconosciuta, fino a quando non ho cliccato su "run". La compilazione è riuscita e il metodo rapido ha funzionato.