Как мне определить и использовать 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;

}
RexOnRoids
источник
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
};

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

rebelzach
источник
Может ли 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/

Santhos
источник
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
Johannes
источник