2009-06-03 125 views
47

我在Objective-C程序中遇到枚举可见性问题。我有两个头文件,其中一个定义了一个typedef enum。另一个文件需要使用typedef'd类型。在直接C中,我只需要#include另一个头文件,但是在Objective-C中,建议不要在头文件之间使用#import,而应根据需要使用正向@class声明。但是,我无法弄清楚如何转发 - 声明一个枚举类型。前向声明枚举Objective-C

我不需要实际的枚举值,除非在相应的.m实现文件中,我可以安全地将#import带走。那么我怎样才能在头文件中识别typedef enum

+0

对于近期的答案(SWIFT 3,2017年)看在我的答案。 http://stackoverflow.com/a/42009056/342794 – lal 2017-05-03 19:49:33

回答

18

继续并使用#import。人们推荐尽可能使用@class的唯一原因是因为它使您的代码在编译时稍微快一点。但是,#import不存在另一个.h文件的问题。事实上,在扩展另一个课程时,你需要做到这一点。

+1

有没有什么办法可以在不使用#import的情况下进行上述操作?简单地做一个`typedef int EnumName`呢? – 2009-06-03 19:01:53

+1

我不这么认为。见GS的答案的链接:http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c – 2009-06-03 19:09:49

+0

随着#进口编译需要几分钟,且有一定的有线事反正。 – 2011-06-26 19:00:00

16

的回答你的问题是,要么继续前进,导入typedef的头文件或使用通用型像NSInteger的,而不是枚举类型的。

但是,没有导入头文件的原因不仅仅是编译速度。

不导入头文件还可以减少无意中访问无关的类。

例如,假设您有一个TrackFileChanges类,用于跟踪文件系统以更改特定文件,并且您有一个用于存储文件缓存数据的CachedFile类。后者可能会使用TrackFileChanges *类型的私有ivar,但是对于CachedFile的使用,这只是一个实现细节(理想情况下,ivar会使用新的运行时自动生成私有属性,但这不可能,重新使用旧的运行时间)。

因此,#import“CachedFile.h”可能不需要或不想访问TrackFileChanges.h的客户端。如果他们这样做,他们应该通过#importing它自己来清楚。通过在CachedFile.h中使用#import“TrackFileChanges.h”的@class TrackFileChanges instea,可以改进封装。

但所有这一切说,从第二个头文件导入头文件没有错,如果第二个头想要公开第一个到所有客户端。例如,声明类的头文件需要直接导入到头文件的子类中,而声明协议的头文件可能会直接导入(尽管您可以使用@protocol ABC来避免这种情况)。

4

如果您在使用编译器扩展都OK,你可以在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) { 

} 

注:这将触发-Wpedantic警告。


如果您正在使用C++ 11,你应该使用自己的枚举,这是安全的转发声明 - 例如enum class Enum:uint8_t;(不是编译器扩展)。

15

最近的方式(SWIFT 3;可2017年)转发在Objective-C声明枚举(NS_ENUM/NS_OPTION)是使用以下:

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