Objective-C中的前向声明枚举

时间:2009-06-03 18:52:10

标签: objective-c enums typedef extern

我在Objective-C程序中遇到enum可见性问题。我有两个头文件,一个定义typedef enum。另一个文件需要使用typedef'd类型。

在C语言中,我只是#include另一个头文件,但在Objective-C中,建议不要在头文件之间使用#import,而是使用前向@class声明需要。但是,我无法弄清楚如何转发声明枚举类型。

我不需要实际的枚举值,除了相应的.m实现文件,我可以放心#import。那么如何才能在标题中识别typedef enum

6 个答案:

答案 0 :(得分:42)

最近的方式(Swift 3; 2017年5月)转发声明在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 */`

答案 1 :(得分:15)

您的问题的答案是继续导入typedef头文件或使用类似NSInteger的泛型类型而不是枚举类型。

但是,除了编译速度之外,还有更多理由不导入头文件。

不导入头文件也可以减少您对无关类的无意访问。

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

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

但是,如果第二个头想要将第一个头文件暴露给所有客户端,那么从第二个头文件导入头文件没有任何错误。例如,声明类的头文件需要直接在子类化头文件中导入,并且可以直接导入声明协议的头文件(尽管你可以使用@protocol ABC;为了避免这种情况)。

答案 2 :(得分:14)

继续使用#import。人们建议在可能的情况下使用@class的唯一原因是因为它使您的代码编译速度稍快。但是,#import来自另一个.h文件没有问题。实际上,在扩展另一个类时需要这样做。

答案 3 :(得分:4)

如果你可以使用编译器扩展,你可以在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;(不是编译器扩展)。

答案 4 :(得分:1)

在Objective C .h文件中对我进行枚举的向前声明的工作是在ProjectName-Swift.h文件中查找并查看它的内容,恰好是以下内容:

枚举SwiftEnumName:NSInteger;

我需要此前向声明,因为我的函数参数类型为SwiftEnumName。而且这也不允许我将ProjectName-Swift.h导入放入Objective C .h文件中。

然后在Objective C .m文件中,我只添加了#import“ ProjectName-Swift.h”,并正常使用了SwiftEnum。

这是使用Swift 4.1.2。

答案 5 :(得分:-2)

无论如何,您必须#import他们或创建一个仅包含typedef的单独的头文件。不在头中导入头文件会使编译更快,但不会改变任何其他内容。

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