Как мне определить и использовать ENUM в Objective-C?


180

Я объявил enum в своем файле реализации, как показано ниже, и объявил переменную этого типа в моем интерфейсе как PlayerState thePlayerState; и использовал переменную в моих методах. Но я получаю ошибки, утверждающие, что это не объявлено. Как правильно объявить и использовать переменную типа PlayerState в моих методах ?:

В файле .m

@implementation View1Controller

    typedef enum playerStateTypes
        {
            PLAYER_OFF,
            PLAYER_PLAYING,
            PLAYER_PAUSED
        } PlayerState;

в .h файле:

@interface View1Controller : UIViewController {

    PlayerState thePlayerState;

в каком-то методе в .m файле:

-(void)doSomethin{

thePlayerState = PLAYER_OFF;

}

2
Теперь тип перечисления thePlayerState. Кем становится playerStateTypes?
— user4951

3
Для получения информации о NS_ENUM и его последнем современном синтаксисе см. Публикацию NS_ENUM & NS_OPTIONS от Mattt Thompson.
— Базилик Бурк

Ответы:


109

Вы typedefдолжны быть в файле заголовка (или в другом файле, который #importдобавлен в ваш заголовок), потому что в противном случае компилятор не будет знать, какой размер сделать PlayerStateivar. Кроме этого, это выглядит нормально для меня.


Возможность поместить это в отдельный файл казалась правильной в моем случае. Я не знаю, хороший ли это подход, но мне нужно было использовать одно и то же перечисление в двух разных ViewControllers (self и делегат / источник данных). Импорт заголовка делегата / источника данных привел к ошибке и кажется слишком большим для простой необходимости. Поэтому я создал новый файл .h с объявленным enum и импортировал его в оба файла viewControllers.h. Работал как шарм.
— Леандро Алвес

7
Следует порекомендовать использовать макрос NS_ENUM - так как это лучшая практика
— khebbie

1
Вы должны объявить перечисления NS_ENUMв Objective-C, если хотите, чтобы ваше перечисление было доступно в коде Swift.
— смайлиборг

@DaveDeLong, это все еще действует в 2015 году? У меня есть typedefобъявленный в .mфайле, и он компилируется и работает хорошо.
— Юлиан Онофрей

@IulianOnofrei это будет в файле .h, если вам нужно использовать enum в других файлах. Если вам нужно только в одном файле, положить его в файл .m всегда было прекрасно.
— Дейв Делонг,

206

Apple предоставляет макрос для лучшей совместимости кода, включая Swift. Использование макроса выглядит следующим образом.

typedef NS_ENUM(NSInteger, PlayerStateType) {
  PlayerStateOff,
  PlayerStatePlaying,
  PlayerStatePaused
};

Документировано здесь


Может ли Obj C Enums иметь переменные-члены, как в Java? Если так, то как?
— часовщик

Значит, второе решение лучше?
— Юлиан Онофрей

3
Второе решение лучше (использует NS_ENUM), так как оно более современное и теперь требуется в Objective-C, если вы хотите, чтобы ваше перечисление было доступно в коде Swift.
— смайлиборг

Обновлено, чтобы показать второе решение на самом деле лучше.
— rebelzach

В стандартной форме Apple имя типа повторяется для каждого значения перечисления.
— ThomasW

29

В .h:

typedef enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
} PlayerState;

1
Подобный ответ вы можете найти в других SO-вопросах, но когда я просматривал перечисления, сначала возник этот вопрос, поэтому я добавил ответ и здесь.
— Бен Флинн

19

В текущих проектах вы можете использовать макросы NS_ENUM()или NS_OPTIONS().

typedef NS_ENUM(NSUInteger, PlayerState) {
        PLAYER_OFF,
        PLAYER_PLAYING,
        PLAYER_PAUSED
    };

2
... и что более важно сейчас, вы должны объявлять перечисления NS_ENUMв Objective-C, если хотите, чтобы ваше перечисление было доступно в коде Swift.
— смайлиборг

16

Вот как Apple делает это для таких классов, как NSString:

В заголовочном файле:

enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
};

typedef NSInteger PlayerState;

Обратитесь к руководству по кодированию на http://developer.apple.com/


3
Это на самом деле не помогает ОП. Хотя это технически правильно, оно не говорит им, как создать повторно используемое перечисление
— RyanR

24
Ссылка на developer.apple.com не очень полезна. Есть ли другое место, которое вы хотели бы процитировать вместо этого?
— Бретт

Скопируйте / вставьте документацию, которая уже предоставлена, ссылка, которая является главной страницей, действительно не помогает другим людям ...
— Onder OZCAN

3
Сейчас это устарело, смотрите эту страницу developer.apple.com/library/ios/releasenotes/ObjectiveC/…
— Алекс Честер

8

Я рекомендую использовать NS_OPTIONS или NS_ENUM. Вы можете прочитать больше об этом здесь: http://nshipster.com/ns_enum-ns_options/

Вот пример из моего собственного кода с использованием NS_OPTIONS, у меня есть утилита, которая устанавливает подслой (CALayer) на слое UIView для создания границы.

Ч. файл:

typedef NS_OPTIONS(NSUInteger, BSTCMBorder) {
    BSTCMBOrderNoBorder     = 0,
    BSTCMBorderTop          = 1 << 0,
    BSTCMBorderRight        = 1 << 1,
    BSTCMBorderBottom       = 1 << 2,
    BSTCMBOrderLeft         = 1 << 3
};

@interface BSTCMBorderUtility : NSObject

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color;

@end

.M файл:

@implementation BSTCMBorderUtility

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color
{

    // Make a left border on the view
    if (border & BSTCMBOrderLeft) {

    }

    // Make a right border on the view
    if (border & BSTCMBorderRight) {

    }

    // Etc

}

@end
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.