Objective-C中的前向声明枚举

Ste*_*set 66 enums typedef objective-c extern

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

在直接C中,我只是#include其他头文件,但在Objective-C中,建议不要#import在头文件之间使用,而是@class根据需要使用前向声明.但是,我无法弄清楚如何转发声明枚举类型.

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

lal*_*lal 49

最近的方式(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 */`
Run Code Online (Sandbox Code Playgroud)

  • 现在这应该是公认的答案 (6认同)
  • 这应该是Enum前言声明的公认答案 (2认同)
  • 你救了我的命。 (2认同)
  • 如果您在 Swift 中定义“@objc enum”并且需要在“.h”文件中使用该类型,这也很有帮助。您必须以这种方式转发声明(查看您的“-Swift.h”标头以了解原始类型应该是什么) (2认同)

Pet*_*wis 15

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

但是,更有理由不导入头文件而不仅仅是编译速度.

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

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

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

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


Seb*_*lis 11

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

  • 人们建议使用@class来避免#import循环(其中foo.h导入bar.h和bar.h导入foo.h).请参阅此处接受的答案:http://stackoverflow.com/questions/9016478/why-class-instead-of-import-for-viewcontroller-in-appdelegate-h (32认同)
  • 更重要的是@class保护您免受循环导入. (6认同)
  • 对于那些来自C/C++背景的人来说,#import是包含保护的安全. (3认同)