Forward-declare enum en Objective-C

Tengo problemas con la visibilidad enum en un progtwig Objective-C. Tengo dos archivos de encabezado, y uno define un typedef enum . Otro archivo necesita usar el tipo typedef ‘d.

En C directa, simplemente incluiría #include el otro archivo de encabezado, pero en Objective-C, se recomienda no usar #import entre los archivos de encabezado, en lugar de usar las declaraciones forward de @class según sea necesario. Sin embargo, no puedo entender cómo reenviar-declarar un tipo de enumeración.

No necesito los valores enumerados reales, excepto en el archivo de implementación .m correspondiente, donde puedo #import forma segura. Entonces, ¿cómo puedo obtener el typedef enum para ser reconocido en el encabezado?

Adelante y usa #import . La única razón por la que las personas recomiendan usar @class cuando es posible es porque hace que su código sea un poco más rápido de comstackr. Sin embargo, no hay problema con #import un archivo .h de otro. De hecho, debe hacer esto cuando amplíe otra clase.

La forma más reciente (Swift 3; mayo de 2017) de reenviar declarar la enumeración (NS_ENUM / NS_OPTION) en el objective c es usar lo siguiente:

 // 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 */` 

La respuesta a su pregunta es continuar e importar el archivo de encabezado typedef o usar un tipo genérico como NSInteger en lugar del tipo de enumeración.

Sin embargo, hay más razones para no importar un archivo de encabezado que simplemente comstackr la velocidad.

No importar un archivo de encabezado también reduce el acceso inadvertido a clases extrañas.

Por ejemplo, supongamos que tiene una clase TrackFileChanges que realiza un seguimiento del sistema de archivos para ver los cambios en un archivo específico, y tiene una clase CachedFile que almacena datos en caché de un archivo. Este último podría usar un ivar de tipo privado TrackFileChanges *, pero para los usos de CachedFile, esto es simplemente un detalle de implementación (idealmente, el ivar se generaría automáticamente con una propiedad privada usando el nuevo tiempo de ejecución, pero eso no es posible si tú ‘ re usando el tiempo de ejecución anterior).

Entonces, los clientes que #importan “CachedFile.h” probablemente no necesiten o no quieran acceder a TrackFileChanges.h. Y si lo hacen, deben dejarlo en claro al #importarlo ellos mismos. Al usar @class TrackFileChanges instea de #import “TrackFileChanges.h” en CachedFile.h, mejora la encapsulación.

Pero dicho todo esto, no hay nada en contra de importar un archivo de encabezado desde un segundo archivo de encabezado si el segundo encabezado quiere exponer el primero a todos los clientes. Por ejemplo, los archivos de encabezado que declaran clases deben importarse directamente en los archivos de cabecera de subclases, y los archivos de cabecera que declaran protocolos bien pueden importarse directamente (aunque usted puede usar @protocol ABC; para evitar esto).

Si está bien usando las extensiones del comstackdor, puede usar este orden en 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: activará una advertencia de -Wpedantic .


Si está utilizando C ++ 11, debe usar sus enumeraciones, que son seguras para reenviar declarar, por ejemplo, enum class Enum:uint8_t; (no es una extensión de comstackción).

Lo que funcionó para una statement directa de una enumeración para mí en un archivo Objective C .h fue buscar en el archivo ProjectName-Swift.h y ver lo que puso, que resultó ser el siguiente:

enum SwiftEnumName: NSInteger;

Necesitaba esta statement directa porque tenía un tipo de parámetro de función de SwiftEnumName. Y no me deja poner la importación ProjectName-Swift.h en el archivo Objective C .h.

Luego en el archivo Objective C .m acabo de tener el #import “ProjectName-Swift.h” y simplemente usé el SwiftEnum normalmente.

Esto estaba usando Swift 4.1.2.

Tendría que #import todos modos o crear un archivo de encabezado separado que solo contenga typedef . No importar archivos de encabezado en un encabezado hace que la comstackción sea más rápida, pero no cambia nada más.

¿Por qué C ++ no admite la statement de enums?