2009-06-03 70 views
47

我在Objective-C程序中遇到枚舉可見性問題。我有兩個頭文件,其中一個定義了一個typedef enum。另一個文件需要使用typedef'd類型。在直接C中,我只需要#include另一個頭文件,但是在Objective-C中,建議不要在頭文件之間使用#import,而應根據需要使用正向@class聲明。但是,我無法弄清楚如何轉發 - 聲明一個枚舉類型。前向聲明枚舉Objective-C

我不需要實際的枚舉值,除非在相應的.m實現文件中,我可以安全地將#import帶走。那麼我怎樣才能在頭文件中識別typedef enum

+0

對於近期的答案(SWIFT 3,2017年)看在我的答案。 http://stackoverflow.com/a/42009056/342794 – lal 2017-05-03 19:49:33

回答

18

繼續並使用#import。人們推薦儘可能使用@class的唯一原因是因爲它使您的代碼在編譯時稍微快一點。但是,#import不存在另一個.h文件的問題。事實上,在擴展另一個課程時,你需要做到這一點。

+1

有沒有什麼辦法可以在不使用#import的情況下進行上述操作?簡單地做一個`typedef int EnumName`呢? – 2009-06-03 19:01:53

+1

我不這麼認爲。見GS的答案的鏈接:http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c – 2009-06-03 19:09:49

+0

隨着#進口編譯需要幾分鐘,且有一定的有線事反正。 – 2011-06-26 19:00:00

16

的回答你的問題是,要麼繼續前進,導入typedef的頭文件或使用通用型像NSInteger的,而不是枚舉類型的。

但是,沒有導入頭文件的原因不僅僅是編譯速度。

不導入頭文件還可以減少無意中訪問無關的類。

例如,假設您有一個TrackFileChanges類,用於跟蹤文件系統以更改特定文件,並且您有一個用於存儲文件緩存數據的CachedFile類。後者可能會使用TrackFileChanges *類型的私有ivar,但是對於CachedFile的使用,這只是一個實現細節(理想情況下,ivar會使用新的運行時自動生成私有屬性,但這不可能,重新使用舊的運行時間)。

因此,#import「CachedFile.h」可能不需要或不想訪問TrackFileChanges.h的客戶端。如果他們這樣做,他們應該通過#importing它自己來清楚。通過在CachedFile.h中使用#import「TrackFileChanges.h」的@class TrackFileChanges instea,可以改進封裝。

但所有這一切說,從第二個頭文件導入頭文件沒有錯,如果第二個頭想要公開第一個到所有客戶端。例如,聲明類的頭文件需要直接導入到頭文件的子類中,而聲明協議的頭文件可能會直接導入(儘管您可以使用@protocol ABC來避免這種情況)。

4

如果您在使用編譯器擴展都OK,你可以在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;(不是編譯器擴展)。

15

最近的方式(SWIFT 3;可2017年)轉發在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 */`