Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Objective-C中正向声明枚举_Objective C_Enums_Typedef_Extern - Fatal编程技术网

在Objective-C中正向声明枚举

在Objective-C中正向声明枚举,objective-c,enums,typedef,extern,Objective C,Enums,Typedef,Extern,我在Objective-C程序中遇到枚举可见性问题。我有两个头文件,其中一个定义了typedef enum。另一个文件需要使用typedef'd类型 在straight C中,我只想#包含另一个头文件,但在Objective-C中,建议不要在头文件之间使用#import,而是根据需要使用forward@class声明。但是,我不知道如何前向声明枚举类型 我不需要实际的枚举值,除了在相应的.m实现文件中,在那里我可以安全地#导入。那么如何才能在标头中识别typedef enum 继续使用#导入。人

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

在straight C中,我只想
#包含
另一个头文件,但在Objective-C中,建议不要在头文件之间使用
#import
,而是根据需要使用forward
@class
声明。但是,我不知道如何前向声明枚举类型


我不需要实际的枚举值,除了在相应的
.m
实现文件中,在那里我可以安全地
#导入
。那么如何才能在标头中识别
typedef enum

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

您必须导入它们,或者创建一个单独的头文件,其中只包含
类型定义。不在头文件中导入头文件可以加快编译速度,但不会改变任何其他内容


您的问题的答案是要么继续导入typedef头文件,要么使用NSInteger之类的泛型类型,而不是enum类型

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

不导入头文件也会减少对无关类的意外访问

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

因此,导入“CachedFile.h”的客户端可能不需要或不希望访问TrackFileChanges.h。如果他们真的这么做了,他们应该通过自己进口来明确这一点。通过在CachedFile.h中使用@class TrackFileChanges而不是#import“TrackFileChanges.h”,可以改进封装


尽管如此,如果第二个头文件想要向所有客户机公开第一个头文件,那么从第二个头文件导入头文件并没有什么不好的。例如,声明类的头文件需要在子类化头文件中直接导入,而声明协议的头文件很可能直接导入(尽管您可以使用@protocol ABC;来避免这种情况)。

如果您可以使用编译器扩展名,则可以使用以下顺序:

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类enum:uint8\t(不是编译器扩展)。

在objective-c中向前声明枚举(NS_enum/NS_选项)的最新方法(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 */`

对于我来说,在目标C.h文件中向前声明枚举的工作是查看ProjectName Swift.h文件,看看它放了什么,碰巧是以下内容:

// 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 */`
枚举快速名称:NSInteger

我需要这个转发声明,因为我有一个函数参数类型SwiftEnumName。它不允许我将ProjectName Swift.h import放在Objective C.h文件中

然后在Objective C.m文件中,我只是在其中输入了#import“ProjectName Swift.h”,并且正常使用了swiftemum


这是使用Swift 4.1.2实现的。

在不使用#导入的情况下,是否可以实现上述功能?简单地做一个
typedef int EnumName
怎么样?我不这么认为。请参阅gs答案中的链接:人们建议使用@class来避免导入周期(其中foo.h导入bar.h,bar.h导入foo.h)。请参见此处接受的答案:更重要的是@class保护您不受循环导入的影响。#对于那些来自C/C++背景的人来说,导入是包括保护安全的。您可以将此答案简化为:
typedef enum enum enum
然后在方法定义和声明中使用Enum。我昨天才开始研究typedef NS_Enum,作为清理旧的Objective C代码的一种方法-这个答案对我很有用。@lal,这对int变量非常有用。我刚刚发布了一个关于如何对浮点变量使用typedef enum的问题。希望您能够回答它-这应该是Enum forward declarationYou Save my life的公认答案。如果您在Swift中定义了
@objc Enum
,并且需要在
.h
文件中使用该类型,这也会很有帮助。您必须以这种方式转发声明它(查看
-Swift.h
标题以查看原始类型)