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

#objective-c #enums

#objective-c #перечисления

Вопрос:

Я работаю над несколькими проектами iOS, где, я думаю, перечисленные типы данных были бы мне полезны. Например, у меня есть игра, в которой игрок может ходить в нескольких направлениях. Я мог бы просто определить четыре константы со строковыми значениями как kDirectionUp , kDirectionDown и т.д.

Я думаю, что перечисляемый тип был бы здесь лучше. Это правильно? Если да, то как мне определить перечисление здесь, чтобы я мог позже сравнивать значения? (Как в, if(someValue == kDirectionUp){} )

Ответ №1:

Это звучит как правильный поступок.

Создавать перечисления в Objective-C действительно просто, используя определения типов в стиле C. Например, в одном из моих заголовочных файлов у меня есть следующее определение типа:

 typedef enum {
  CFPosterViewTypePoster = 0,
  CFPosterViewTypeStart, // 1
  CFPosterViewTypeEnd,   // 2
  ....                   // 3
} CFPosterViewType;   
  

Вы определяете объект CFPosterViewType и присваиваете ему одно из значений:

 CFPosterViewType posterType = CFPosterViewTypeStart;
  

При сравнении значений CFPosterViewType это так же просто, как выполнить следующее:

 if (posterType == CFPosterViewTypePoster) {
    // do something
}
  

Обратите внимание, что закомментированные числа в перечислении выше являются неявными значениями. Если вы хотите сделать что-то по-другому, скажем, определить битовую маску или что-нибудь еще, где вам нужны значения, отличные от значений по умолчанию, вам нужно явно определить их.

Ответ №2:

В заголовочном файле определите enum тип, например:

 // SomeHeaderFile.h
typedef enum {
    MOPlayerDirectionNone,
    MOPlayerDirectionUp,
    MOPlayerDirectionDown,
    …
} MOPlayerDirection;
  

Всякий раз, когда вам нужно использовать MOPlayerDirection , #import этот файл заголовка. Затем вы можете использовать его как тип, а также его возможные значения.

Например:

 #import "SomeHeaderFile.h"

@interface MOPlayer : NSObject {
    MOPlayerDirection currentDirection;
}

- (void)moveToDirection:(MOPlayerDirection)direction;
- (void)ha<
@end
  

и:

 #import "SomeHeaderFile.h"
#import "MOPlayer.h"

@implementation MOPlayer

- (id)init {
    self = [super init];
    if (self) {
        currentDirection = MOPlayerDirectionNone;
    }
    return self;
}

- (void)moveToDirection:(MOPlayerDirection)direction {
    currentDirection = direction;

    switch (currentDirection) {
        case MOPlayerDirectionUp:
            // do something
            break;

        case MOPlayerDirectionDown:
            // do something
            break;
    }
}

- (void)halt {
    if (currentDirection != MOPlayerDirectionNone) {
        // do something
        currentDirection = MOPlayerDirectionNone;
    }
}

@end
  

Если перечисление тесно связано с классом, обычно его определяют в том же заголовочном файле, что и объявление класса. В приведенном выше примере вместо определения MOPlayerDirection в SomeHeaderFile.h вы могли бы вместо этого определить его в MOPlayer.h.

Комментарии:

1. Я думаю, MOPlayerDirection *currentDirection вероятно, должно быть MOPlayerDirection currentDirection ;-). Вероятно, это не имело бы значения здесь, но более новый способ выполнить typedef часть, похоже, состоит в том, чтобы поместить явное typedef NSUInteger MOPlayerDirection; после перечисления, чтобы помочь компилятору.

2. @NSGod Спасибо; автопилот FTL. 🙂

3. @NSGod Я не совсем понимаю, как NSUInteger это помогло бы компилятору. Компилятор волен выбирать базовый тип данных для enum , и тип данных гарантированно будет одним из целочисленных типов данных.

4. @NSGod Хотя это было бы верно для перечислений в битовой маске.

Ответ №3:

Просто определите их в верхней части вашего файла:

 enum    // direction types
{
    kDirectionUp = 0,
    kDirectionDown, // 1
    kDirectionLeft, // 2
    kDirectionRight // 3

};
  

затем вы можете вызывать по мере необходимости:

 if(someValue == kDirectionUp){ // do something }