2009-06-03 8 views
47

Sto avendo problemi con la visibilità enum in un programma di Objective-C. Ho due file header e uno definisce uno typedef enum. Un altro file deve utilizzare il tipo typedef.Forward-declare enum in Objective-C

in rettilineo C, vorrei semplicemente #include l'altro file di intestazione, ma in Objective-C, si consiglia di non utilizzare #import tra le file header, utilizzando invece avanti @class dichiarazioni in base alle esigenze. Tuttavia, non riesco a capire come inoltrare-dichiarare un tipo di enumerazione.

Non ho bisogno dei valori effettivi enumerati, tranne nel file di implementazione .m corrispondente, dove posso tranquillamente #import di distanza. Quindi, come posso ottenere il riconoscimento typedef enum nell'intestazione?

+0

Per tutta risposta recente (Swift 3, 2017) guarda alla mia risposta. http://stackoverflow.com/a/42009056/342794 – lal

risposta

18

Vai avanti e utilizzare #import. L'unico motivo per cui la gente consiglia di utilizzare @class quando possibile è perché rende il codice leggermente più veloce da compilare. Tuttavia, non vi è alcun problema con lo #import di un file .h da un altro. In effetti, devi farlo quando estendi un'altra classe.

+1

Esiste un modo di cui sopra, senza utilizzare #import? Che dire semplicemente facendo un typedef int EnumName? –

+1

Non penso. Vedi il link nella risposta di gs: http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c –

+0

Con la compilazione #import occorrono minuti, e comunque c'è qualche cosa cablata. –

0

Si dovrebbe avere o #import comunque creare un file di intestazione separato contenente solo il typedef. Non importare i file di intestazione in un'intestazione rende la compilazione più veloce, ma non cambia nient'altro.

Why doesn't C++ support forward declaration of enums?

16

La risposta alla tua domanda è o andare avanti e importare il file di intestazione typedef o di utilizzare un tipo generico come NSInteger invece del tipo enum.

Tuttavia, non v'è più motivo per non importare un file di intestazione di una semplice compilazione di velocità.

Non l'importazione di un file di intestazione riduce anche l'accesso involontario a classi estranee.

Ad esempio, supponiamo di disporre di una classe TrackFileChanges che tiene traccia del file system per le modifiche a un file specifico e di una classe CachedFile che memorizza i dati memorizzati nella cache da un file. Quest'ultimo potrebbe utilizzare un ivar privato di tipo TrackFileChanges *, ma per gli usi di CachedFile, questo è semplicemente un dettaglio di implementazione (idealmente, l'ivar verrebbe generato automaticamente con una proprietà privata utilizzando il nuovo runtime, ma questo non è possibile se si ' ri usando il vecchio tempo di esecuzione).

così i clienti che #import "CachedFile.h" probabilmente non hanno bisogno o vogliono l'accesso a TrackFileChanges.h. E se lo fanno, dovrebbero renderlo chiaro # importando loro stessi. Utilizzando @class TrackFileChanges instea di #import "TrackFileChanges.h" in CachedFile.h si migliora l'incapsulamento.

Ma tutto ciò che ha detto, non c'è niente di awrong con l'importazione di un file di intestazione da un secondo file di intestazione se la seconda intestazione vuole esporre il primo a tutti i clienti. Ad esempio, i file di intestazione che dichiarano le classi devono essere importati direttamente in file di intestazione di sottoclassi e i file di intestazione che dichiarano che i protocolli potrebbero essere importati direttamente (sebbene tu possa usare @protocol ABC; per evitare ciò).

4

Se vi sono ok utilizzando le estensioni del compilatore, è possibile utilizzare questo ordine in Clang:

enum Enum; 
typedef enum Enum Enum2; 

void f(Enum2); // ok. it sees this type's true name. 

enum Enum { 
    E_1 
}; 

// ok. now its declaration is visible and we can use it. 

void f(Enum2 e) { 

} 

Nota: Si attiverà un allarme -Wpedantic.


Se si utilizza C++ 11, è necessario utilizzare le relative enumerazioni, che è sicuro inoltrare dichiarare - ad es. enum class Enum:uint8_t; (non un'estensione del compilatore).

+1

È possibile semplificare questa risposta a questo: 'typedef enum Enum Enum;' Quindi basta usare Enum nella definizione del metodo e nella dichiarazione. –

15

più recenti modo (Swift 3; maggio 2017) per inoltrare dichiarare l'enum (NS_ENUM/NS_OPTION) in Objective-C è quello di utilizzare il seguente:

// Forward declaration for XYZCharacterType in other header say XYZCharacter.h 
typedef NS_ENUM(NSUInteger, XYZCharacterType); 


// Enum declaration header: "XYZEnumType.h" 
#ifndef XYZCharacterType_h 
#define XYZCharacterType_h 

typedef NS_ENUM(NSUInteger, XYZEnumType) { 
    XYZCharacterTypeNotSet, 
    XYZCharacterTypeAgent, 
    XYZCharacterTypeKiller, 
}; 

#endif /* XYZCharacterType_h */` 
+1

ha funzionato per me con swift 3 – stringRay2014

+3

Al giorno d'oggi dovrebbe essere la risposta accettata – citxx

+1

Ho iniziato a guardare typedef NS_ENUM solo ieri come un modo per ripulire il vecchio codice Objective C - e questa risposta ha funzionato per me. – Greg