2009-06-03 12 views
47

Mam problem z widocznością enum w programie Objective-C. Mam dwa pliki nagłówkowe, a jeden definiuje typedef enum. Inny plik musi używać typu "d" w wersji typedef.Forward-declare wylicza w Objective-C

W prostych C, ja po prostu #include drugi nagłówek pliku, ale w Objective-C, zaleca się nie używać #import między plikami nagłówka, zamiast korzystania forward @class deklaracji, ile potrzeba. Jednak nie mogę dowiedzieć się, jak przekazywać dalej - zadeklaruj typ wyliczeniowy.

Nie potrzebuję rzeczywistych wyliczonych wartości, z wyjątkiem odpowiedniego pliku implementacyjnego .m, w którym mogę bezpiecznie odejść #import. Więc jak mogę uzyskać rozpoznanie typedef enum w nagłówku?

+0

Na ostatniej odpowiedzi (Swift 3, 2017) wyglądać w mojej odpowiedzi. http://stackoverflow.com/a/42009056/342794 – lal

Odpowiedz

18

Śmiało i użyj #import. Jedynym powodem, dla którego ludzie zalecają używanie @class, gdy jest to możliwe, jest to, że sprawia, że ​​twój kod nieco szybciej się kompiluje. Jednak nie ma problemu z #import z jednego pliku .h z innego. W rzeczywistości musisz to zrobić, jeśli chcesz rozszerzyć kolejną klasę.

+1

Czy jest jakikolwiek sposób powyższego jest możliwy, bez użycia #import? Co powiesz na zrobienie 'typedef int EnumName'? –

+1

Nie sądzę. Zobacz link w odpowiedzi gs: http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c –

+0

Z kompilacją #import potrzebuje minut, a i tak jest jakaś wirediarka. –

0

W każdym razie musisz albo #import albo utworzyć oddzielny plik nagłówkowy zawierający tylko typedef. Nie importowanie plików nagłówkowych w nagłówku powoduje, że kompilacja jest szybsza, ale nie zmienia niczego innego.

Why doesn't C++ support forward declaration of enums?

16

Odpowiedź na to pytanie jest iść do przodu i albo zaimportować plik nagłówka typedef lub używać typu rodzajowego jak NSInteger zamiast typu wyliczeniowego.

Istnieje jednak więcej powodów, dla których nie należy importować pliku nagłówkowego niż tylko prędkość kompilacji.

Brak importowania pliku nagłówkowego zmniejsza również nieumyślny dostęp do obcych klas.

Załóżmy na przykład, że masz klasę TrackFileChanges, która śledzi system plików w celu zmiany określonego pliku, i masz klasę CachedFile, która przechowuje buforowane dane z pliku. Ten ostatni może używać prywatnego ivar typu TrackFileChanges *, ale w przypadku użycia CachedFile jest to po prostu szczegół implementacji (najlepiej, że ivar byłby automatycznie generowany z prywatną własnością przy użyciu nowego środowiska wykonawczego, ale to nie jest możliwe, jeśli " ponownie używać starego czasu pracy).

Tak więc klienci, którzy #import "CachedFile.h" prawdopodobnie nie potrzebują lub nie chcą dostępu do TrackFileChanges.h. A jeśli tak, to powinni to wyjaśnić, # implikując to samemu. Używając @class TrackFileChanges instea z #import "TrackFileChanges.h" w CachedFile.h poprawisz enkapsulację.

Ale wszystko, co powiedzieliśmy, nie ma nic złego w importowaniu pliku nagłówkowego z drugiego pliku nagłówkowego, jeśli drugi nagłówek chce wystawić pierwszego do wszystkich klientów. Na przykład pliki nagłówkowe, które deklarują klasy, muszą być importowane bezpośrednio w podklasach plików nagłówkowych, a pliki nagłówkowe deklarujące protokoły mogą być importowane bezpośrednio (chociaż możesz użyć @ protocool ABC; aby tego uniknąć).

4

Jeśli są ok użyciu rozszerzenia kompilatora, można użyć tego polecenia w 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) { 

} 

Uwaga: To wywoła -Wpedantic ostrzeżenie.


Jeśli korzystasz z C++ 11, powinieneś użyć ich wyliczeń, które można bezpiecznie przesyłać dalej - np. enum class Enum:uint8_t; (bez rozszerzenia kompilatora).

+1

Możesz uprościć tę odpowiedź na to: 'typedef enum Enum Enum;' Następnie użyj Enum w definicji i deklaracji metody. –

15

Najnowsze sposób (Swift 3, od maja 2017) do przekazania zadeklarować enum (NS_ENUM/NS_OPTION) w Objective-C jest użycie następujących:

// 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

pracował dla mnie z szybkim 3 – stringRay2014

+3

W dzisiejszych czasach to powinna być akceptowana odpowiedź – citxx

+1

Zacząłem patrzeć na typedef NS_ENUM tylko wczoraj jako sposób na oczyszczenie starego kodu C celu - i ta odpowiedź zadziałała. – Greg

Powiązane problemy