我在Objective-C程序中遇到enum可见性问题。我有两个头文件,一个定义typedef enum
。另一个文件需要使用typedef
'd类型。
在C语言中,我只是#include
另一个头文件,但在Objective-C中,建议不要在头文件之间使用#import
,而是使用前向@class
声明需要。但是,我无法弄清楚如何转发声明枚举类型。
我不需要实际的枚举值,除了相应的.m
实现文件,我可以放心#import
。那么如何才能在标题中识别typedef enum
?
答案 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
的单独的头文件。不在头中导入头文件会使编译更快,但不会改变任何其他内容。