Что такое перечисление typedef в Objective-C?

Я не думаю, что я принципиально понимаю, что такое enum, и когда его использовать.

Например:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Что действительно объявляется здесь?

1053
задан 02 апр. '09 в 0:59
источник поделиться
15 ответов

Объявляются три вещи: объявляется анонимный объявленный тип, ShapeType объявляется typedef для этого анонимного перечисления, а три имени kCircle, kRectangle и kOblateSpheroid объявляются как интегральные постоянные.

Позвольте сломать это. В простейшем случае перечисление может быть объявлено как

enum tagname { ... };

Это объявляет перечисление с тегом tagname. В C и Objective-C (но не С++) любые ссылки на это должны предшествовать ключевому слову enum. Например:

enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++

Чтобы избежать использования ключевого слова enum везде, можно создать typedef:

enum tagname { ... };
typedef enum tagname tagname;  // declare 'tagname' as a typedef for 'enum tagname'

Это можно упростить в одну строку:

typedef enum tagname { ... } tagname;  // declare both 'enum tagname' and 'tagname'

И, наконец, если нам не нужно использовать enum tagname с ключевым словом enum, мы можем сделать анонимный enum и объявить его только с именем typedef:

typedef enum { ... } tagname;

Теперь, в этом случае, мы объявляем ShapeType именем typedef'ом анонимного перечисления. ShapeType действительно является только интегральным типом и должен использоваться только для объявления переменных, которые содержат одно из значений, указанных в объявлении (т.е. один из kCircle, kRectangle и kOblateSpheroid). Однако вы можете присвоить переменной ShapeType другое значение путем кастинга, поэтому вам нужно быть осторожным при чтении значений перечисления.

Наконец, kCircle, kRectangle и kOblateSpheroid объявлены как интегральные константы в глобальном пространстве имен. Поскольку конкретные значения не заданы, они присваиваются целым целым числам начиная с 0, поэтому kCircle равно 0, kRectangle равно 1, а kOblateSpheroid равно 2.

1540
ответ дан 02 апр. '09 в 1:22
источник

Apple рекомендует определять перечисления как это начиная с Xcode 4.4:

typedef enum ShapeType : NSUInteger {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Они также предоставляют удобный макрос NS_ENUM:

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

Эти определения обеспечивают более строгую проверку типов и лучшее завершение кода. Я не смог найти официальную документацию NS_ENUM, но вы можете посмотреть видео "Modern Objective-C" с сессии WWDC 2012 здесь.

ОБНОВЛЕНИЕ: Ссылка на официальную документацию здесь.

245
ответ дан 06 марта '13 в 12:43
источник

Перечисление объявляет набор упорядоченных значений - typedef просто добавляет к этому удобное имя. 1-й элемент 0 и т.д.

typedef enum {
Monday=1,
...
} WORKDAYS;

WORKDAYS today = Monday;

Выше приведено только перечисление тегов shapeType.

47
ответ дан 15 марта '12 в 19:31
источник

Пользовательский тип, который имеет возможные значения kCircle, kRectangle или kOblateSpheroid. Однако значения внутри перечисления (kCircle и т.д.) Видны вне перечисления. Важно помнить об этом (например, int i = kCircle;).

34
ответ дан 02 апр. '09 в 1:04
источник

Обновление для 64-битного изменения: Согласно apple docs о 64-битных изменениях,

Также перечислены перечисления: в компиляторе LLVM перечисленные типы могут определите размер перечисления. Это означает, что некоторые перечислены типы могут также иметь размер, который больше, чем вы ожидаете. решение, как и во всех других случаях, заключается в том, чтобы не делать предположений о размер данных. Вместо этого назначьте любые перечисленные значения переменной с правильным типом данных

Итак, вы должны создать перечисление с типом, как показано ниже, если вы поддерживаете 64-разрядную версию.

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

или

typedef enum ShapeType : NSUInteger {
   kCircle,
   kRectangle,
   kOblateSpheroid
} ShapeType;

В противном случае это приведет к предупреждению как Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Обновление для быстрого программирования:

В swift есть синтаксическое изменение.

enum ControlButtonID: NSUInteger {
        case kCircle , kRectangle, kOblateSpheroid
    }
28
ответ дан 29 янв. '14 в 16:08
источник

Enum - это тип данных, определенных пользователем. ЕДИНСТВЕННЫЕ ТИПЫ ДАННЫХ Переменные переменных типа данных могут принимать только значения, которые были ранее объявлены.

enum month { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
enum month this_month;

this_month = feb;

В приведенном выше объявлении месяц объявляется как перечислимый тип данных. Он состоит из набора значений, jan-dec. Численно, jan получает значение 1, feb значение 2 и т.д.

Указанная переменная this_month имеет тот же тип, что и месяц, а затем присваивается значение, связанное с feb. This_month не может быть назначено никаких значений за пределами тех, которые указаны в списке инициализации для объявления месяца.

25
ответ дан 17 окт. '12 в 15:08
источник

Перечисление (аббревиатура перечисления) используется для перечисления набора значений (счетчиков). Значение представляет собой любую абстрактную вещь, представленную символом (словом). Например, базовое перечисление может быть

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };

Это перечисление называется анонимным, потому что у вас нет символа для его названия. Но это все еще совершенно правильно. Просто используйте его так:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;

Ok. Жизнь прекрасна, и все идет хорошо. Но однажды вам нужно повторно использовать это перечисление, чтобы определить новую переменную для хранения myGrandFatherPantSize, затем вы пишете:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;

Но тогда у вас есть ошибка компилятора "переопределение перечислителя". На самом деле проблема заключается в том, что компилятор не уверен, что вы сначала перечислите, а ваша вторая описывает одно и то же.

Затем, если вы хотите повторно использовать один и тот же набор счетчиков (здесь xs... xxxxl) в нескольких местах, вы должны пометить его уникальным именем. Во второй раз, когда вы используете этот набор, вам просто нужно использовать тег. Но не забывайте, что этот тег не заменяет слово перечисления, а просто набор счетчиков. Затем позаботьтесь, как обычно, использовать перечисление. Вот так:

// Here the first use of my enum
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize; 
// here the second use of my enum. It works now !
enum sizes myGrandFatherPantSize;

вы также можете использовать его в определении параметра:

// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;

Можно сказать, что переписывание enum везде не удобно и делает код немного странным. Ты прав. Реальный тип будет лучше.

Это последний шаг нашего великого прогресса на саммите. Просто добавив typedef, мы преобразуем наше перечисление в реальный тип. О, последнее, typedef не допускается в вашем классе. Затем определите свой тип чуть выше. Сделайте это так:

// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type

@interface myClass {
   ...
   size_type myGrandMotherDressSize, myGrandFatherPantSize;
   ...
}

Помните, что тег является необязательным. Тогда, поскольку здесь в этом случае мы не будем отмечать перечисления, а просто определять новый тип. Тогда нам это больше не нужно.

// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;

@interface myClass : NSObject {
  ...
  size_type myGrandMotherDressSize, myGrandFatherPantSize;
  ...
}
@end

Если вы разрабатываете в ObjectiveC с XCode, я позволяю вам открывать интересные макросы с префиксом NS_ENUM. Это должно помочь вам легко определить хорошие перечисления и, кроме того, поможет статическому анализатору выполнить некоторые интересные проверки перед компиляцией.

Хорошее перечисление!

23
ответ дан 10 марта '13 в 21:23
источник

typedef полезно для переопределения имени существующего типа переменной. Он обеспечивает короткий и значимый способ вызова типа данных. например:

typedef unsigned long int TWOWORDS;

здесь тип unsigned long int переопределяется как тип TWOWORDS. Таким образом, мы можем теперь объявлять переменные типа unsigned long int путем записи,

TWOWORDS var1, var2;

вместо

unsigned long int var1, var2;
10
ответ дан 18 июня '13 в 9:03
источник
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

то вы можете использовать его как: -

 ShapeType shape;

и

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

теперь вы можете использовать его как: -

enum ShapeType shape;
7
ответ дан 25 дек. '13 в 9:14
источник

enum используется для присвоения значения элементам перечисления, которые не могут быть выполнены в struct. Поэтому каждый раз вместо доступа к полной переменной мы можем сделать это по значению, которое мы присваиваем переменным в перечислении. По умолчанию он начинается с назначения 0, но мы можем назначить ему любое значение, а следующей переменной в перечислении будет присвоено значение предыдущего значения +1.

3
ответ дан 16 марта '14 в 15:45
источник

typedef позволяет программисту определить один тип Objective-C как другой. Например,

typedef int Counter; определяет тип Counter, чтобы он был эквивалентен типу int. Это значительно улучшает читаемость кода.

2
ответ дан 28 дек. '14 в 1:42
источник

Typedef - это ключевое слово в C и С++. Он используется для создания новых имен для базовых типов данных (char, int, float, double, struct и enum).

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Здесь он создает нумерованный тип данных ShapeType, и мы можем писать новые имена для типа перечисления ShapeType, как указано ниже

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;
2
ответ дан 16 нояб. '15 в 15:33
источник

Вы можете использовать в нижнем формате, Исходное значение по умолчанию, начиная с 0, поэтому

  • kCircle = 0,
  • kRectangle равен 1,
  • kOblateSpheroid - 2.

Вы можете назначить свое собственное начальное значение.

typedef enum : NSUInteger {
    kCircle, // for your value; kCircle = 5, ...
    kRectangle,
    kOblateSpheroid
} ShapeType;

ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
2
ответ дан 30 марта '16 в 12:41
источник
typedef NS_OPTIONS(NSInteger, BaseButtonType){
    BaseBarButtonType = 1,
    BasePrimaryButtonType,      //  Yellow Button
    BaseSecondaryButtonType,    //  Light Gray Button
    BaseTertiaryButtonType      //  Red Button
};`declaration`

Объявить:

-(void)setButtonType:(BaseButtonType)iButtonType{
    buttonType = iButtonType; 
}`set button enum`

Вы можете использовать с другим случаем:

switch (buttonType) {
        case BasePrimaryButtonType:
             break;
        case BaseSecondaryButtonType:
             break;
        case BaseTertiaryButtonType:
             break;
        default:
             break;
    } `Use`
0
ответ дан 03 дек. '17 в 6:56

enum может уменьшить количество типов "ошибок" и сделать код более управляемым

#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER

Определение не имеет ограничений. Это просто замена. Он не способен ограничивать все условия государства. Когда STATE назначен на 5, программа будет неправильной, потому что нет соответствующего состояния. Но компилятор не собирается предупреждать STATE = 5

Так что лучше так использовать

typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;
0
ответ дан 21 июня '18 в 9:29
источник

Другие вопросы по меткам или Задайте вопрос