Objective-C 中的前向声明枚举
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/946489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Forward-declare enum in Objective-C
提问by Stephen Touset
I'm having trouble with enum visibility in an Objective-C program. I have two header files, and one defines a typedef enum. Another file needs to use the typedef'd type.
我在 Objective-C 程序中遇到枚举可见性的问题。我有两个头文件,一个定义了一个typedef enum. 另一个文件需要使用typedef'd 类型。
In straight C, I would simply #includethe other header file, but in Objective-C, it's recommended not to use #importbetween header files, instead using forward @classdeclarations as needed. However, I can't figure out how to forward-declare an enumeration type.
在直接的 C 中,我会简单地#include使用另一个头文件,但在 Objective-C 中,建议不要#import在头文件之间使用,而是@class根据需要使用前向声明。但是,我无法弄清楚如何向前声明枚举类型。
I don't need the actual enumerated values, except in the corresponding .mimplementation file, where I can safely #importaway. So how can I get the typedef enumto be recognized in the header?
我不需要实际的枚举值,除了在相应的.m实现文件中,我可以安全地#import离开。那么我怎样才能typedef enum在标题中识别出来呢?
采纳答案by Sebastian Celis
Go ahead and use #import. The only reason people recommend to use @classwhen possible is because it makes your code slightly faster to compile. However, there is no issue with #importing one .h file from another. In fact, you need to do this when extending another class.
继续使用#import. 人们建议@class在可能的情况下使用的唯一原因是因为它使您的代码编译速度稍快。但是,#import从另一个 .h 文件 ing没有问题。实际上,在扩展另一个类时需要这样做。
回答by lal
Most recent way (Swift 3; May 2017) to forward declare the enum (NS_ENUM/NS_OPTION) in objective-c is to use the following:
在objective-c 中转发声明枚举(NS_ENUM/NS_OPTION)的最新方法(Swift 3;2017 年 5 月)是使用以下内容:
// 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 */`
回答by Peter N Lewis
The answer to your question is to either go ahead and import the typedef header file or to use a generic type like NSInteger instead of the enum type.
你的问题的答案是要么继续导入 typedef 头文件,要么使用像 NSInteger 这样的泛型类型而不是枚举类型。
However, there is more reason to not importing a header file than just compile speed.
但是,除了编译速度之外,还有更多理由不导入头文件。
Not importing a header file also reduces your inadvertent access to extraneous classes.
不导入头文件也会减少您对无关类的无意访问。
For example, say you have a TrackFileChanges class that tracks the file system for changes to a specific file, and you have a CachedFile class that stores cached data from a file. The latter might use a private ivar of type TrackFileChanges*, but for uses of CachedFile, this is simply an implementation detail (ideally, the ivar would be auto-generated with a private property using the new runtime, but thats not possible if you're using the old run time).
例如,假设您有一个 TrackFileChanges 类,用于跟踪文件系统对特定文件的更改,并且您有一个 CachedFile 类,用于存储来自文件的缓存数据。后者可能使用 TrackFileChanges* 类型的私有 ivar,但对于 CachedFile 的使用,这只是一个实现细节(理想情况下,ivar 将使用新的运行时使用私有属性自动生成,但如果你这样做是不可能的)重新使用旧的运行时)。
So clients that #import "CachedFile.h" probably do not need or want access to TrackFileChanges.h. And if they do, they should make it clear by #importing it themselves. By using @class TrackFileChanges instea of #import "TrackFileChanges.h" in CachedFile.h you improve the encapsulation.
因此,#import "CachedFile.h" 的客户端可能不需要或不想访问 TrackFileChanges.h。如果他们这样做了,他们应该自己#importing 来说明这一点。通过在 CachedFile.h 中使用 @class TrackFileChanges instea of #import "TrackFileChanges.h" 可以改进封装。
But all that said, there is nothing awrong with importing a header file from a second header file if the second header wants to expose the first to all clients. For example, header files that declare classes need to be imported directly in subclassing header files, and header files declaring protocols might well be imported directly (although youy can use @protocol ABC; to avoid this).
尽管如此,如果第二个头文件想要向所有客户端公开第一个头文件,那么从第二个头文件导入头文件并没有错。例如,声明类的头文件需要在子类化头文件中直接导入,而声明协议的头文件很可能直接导入(尽管您可以使用@protocol ABC; 来避免这种情况)。
回答by justin
If you are ok using compiler extensions, you could use this order in Clang:
如果您可以使用编译器扩展,则可以在 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) {
}
Note: It will trigger a -Wpedanticwarning.
注意:它会触发-Wpedantic警告。
If you are using C++11, you should use their enums, which are safe to forward declare -- e.g. enum class Enum:uint8_t;(not a compiler extension).
如果您使用的是 C++11,则应该使用它们的枚举,这些枚举可以安全地转发声明——例如enum class Enum:uint8_t;(不是编译器扩展)。
回答by Doug Voss
What worked for a forward declaration of an enum for me in an Objective C .h file was look in the ProjectName-Swift.h file and see what it put, which happened to be the following:
在 Objective C .h 文件中对我的枚举的前向声明起作用的是查看 ProjectName-Swift.h 文件并查看它的内容,这恰好是以下内容:
enum SwiftEnumName : NSInteger;
枚举 SwiftEnumName : NSInteger;
I needed this forward declaration because I had a function parameter type of SwiftEnumName. And it wouldn't let me put the ProjectName-Swift.h import in the Objective C .h file.
我需要这个前向声明,因为我有一个 SwiftEnumName 的函数参数类型。它不会让我将 ProjectName-Swift.h 导入放入 Objective C .h 文件中。
Then in the Objective C .m file I just had the #import "ProjectName-Swift.h" in it and just used the SwiftEnum normally.
然后在 Objective C .m 文件中,我只有 #import "ProjectName-Swift.h" 并且正常使用了 SwiftEnum。
This was using Swift 4.1.2.
这是使用 Swift 4.1.2。
回答by Georg Sch?lly
You'd have to either #importthem anyway or create a separate header file containing only the typedef. Not importing header files in a header makes the compilation faster, but doesn't change anything else.
#import无论如何,您必须要么使用它们,要么创建一个仅包含typedef. 不在头文件中导入头文件会使编译速度更快,但不会更改其他任何内容。

