Вперед-объявить перечисление в Objective-C
у меня возникли проблемы с видимостью перечисления в программе Objective-C. У меня есть два файла заголовка, и один определяет typedef enum. Другой файл должен использовать typedef'D типа.
в прямом C, я бы просто #include другой файл заголовка, но в Objective-C, рекомендуется не использовать #import между заголовочными файлами, вместо этого используя forward @class объявления по мере необходимости. Однако я не могу понять, как переадресовать-объявить тип перечисления.
мне не нужны фактические перечисленные значения, за исключением соответствующих .m - файл, где я могу безопасно #import подальше. Так как же я могу получить typedef enum для распознавания в заголовке?
6 ответов:
идите вперед и используйте
#import. Единственная причина, по которой люди рекомендуют использовать@classкогда это возможно, потому что это делает ваш код немного быстрее компилировать. Однако, нет никаких проблем с#importных .H-файл от другого. На самом деле, вам нужно сделать это при расширении другого класса.
самый последний способ (Swift 3; май 2017) переслать объявление перечисления (NS_ENUM/NS_OPTION) в objective-c заключается в использовании следующего:
// 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 */`
ответ на ваш вопрос заключается в том, чтобы либо продолжить импорт файла заголовка typedef, либо использовать общий тип, такой как NSInteger, вместо типа enum.
тем не менее, есть больше причин не импортировать файл заголовка, чем просто скорость компиляции.
Не импортируя файл заголовка также уменьшает ваш непреднамеренный доступ к посторонним классам.
например, предположим, что у вас есть класс TrackFileChanges, который отслеживает файловую систему для внесения изменений в определенный файл, и у вас есть класс CachedFile, который хранит кэшированные данные из файла. Последний может использовать частный ivar типа TrackFileChanges*, но для использования CachedFile это просто деталь реализации (в идеале, ivar будет автоматически сгенерирован с частным свойством с использованием новой среды выполнения, но это невозможно, если вы используете старое время выполнения).
Итак, клиенты, которые #import " CachedFile.h " вероятно, вам не нужен или не нужен доступ к TrackFileChanges.h. И если они делают, то они должны сделать это ясно, #импортируя его сами. Используя @class TrackFileChanges instea of #import " TrackFileChanges.h " в CachedFile.h вы улучшаете инкапсуляцию.
но все это говорит о том, что нет ничего плохого в импорте файла заголовка из второго файла заголовка, если второй заголовок хочет предоставить первый всем клиентам. Например, файлы заголовков, которые объявляют классы, должны быть импортированы непосредственно в файлы заголовков подклассов, а файлы заголовков, объявляющие протоколы, вполне могут быть импортируется напрямую (хотя вы можете использовать @protocol ABC; чтобы избежать этого).
Если вы в порядке, используя расширения компилятора, вы можете использовать этот порядок в 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;(не расширение компилятора).
Что сработало для прямого объявления перечисления для меня в Objective C .h файл был смотреть в ProjectName-Swift.H-файл и посмотреть, что он поставил, который оказался следующим:
перечисление SwiftEnumName : NSInteger;
Мне нужно было это прямое объявление, потому что у меня был тип параметра функции SwiftEnumName. И это не позволило мне поставить имя проекта-Swift.H импорт в цель C .H-файл.
затем в объективе C .m файл у меня только что был #import " Имяпроекта-Swift.h " в нем и просто использовал SwiftEnum нормально.
Это было с помощью Swift 4.1.2.
вам придется либо
#importих в любом случае или создать отдельный заголовочный файл, содержащий толькоtypedef. Не импортируя заголовочные файлы в заголовке делает компиляцию быстрее, но ничего не меняет.
Comments