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

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

Например:

 typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

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

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

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

 enum tagname { ... }; 

Это объявляет перечисление с тегом tagname . В C и Objective-C (но не 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’ed имя анонимного enums. ShapeType действительно является только интегральным типом и должен использоваться только для объявления переменных, которые содержат одно из значений, указанных в объявлении (то есть, один из kCircle , kRectangle и kOblateSpheroid ). Однако вы можете присвоить переменной ShapeType другое значение путем кастинга, поэтому вам нужно быть осторожным при чтении значений enums.

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

Apple рекомендует определять enums, подобные этому, поскольку 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 здесь .

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

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

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

Вышеупомянутое представляет собой просто перечисление тегов shapeType.

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

Обновление для 64-битного изменения: согласно яблочным документам о 64-битных изменениях,

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

Таким образом, вы должны создать enum с типом, как показано ниже, если вы поддерживаете 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 } 

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 не может быть назначено никаких значений за пределами тех, которые указаны в списке инициализации для объявления месяца.

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

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

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

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

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

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

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

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

 // 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 не допускается в вашем classе. Затем определите свой тип чуть выше. Делай это так:

 // enum definition enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl }; typedef enum sizes size_type @interface myClass { ... size_type myGrandMotherDressSize, myGrandFatherPantSize; ... } 

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

 // enum definition typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type; @interface myClass : NSObject { ... size_type myGrandMotherDressSize, myGrandFatherPantSize; ... } @end 

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

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

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

 typedef unsigned long int TWOWORDS; 

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

 TWOWORDS var1, var2; 

вместо

 unsigned long int var1, var2; 
 typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

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

  ShapeType shape; 

а также

  enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

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

 enum ShapeType shape; 

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

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

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

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

 typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

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

 ShapeType shape1; ShapeType shape2; ShapeType shape3; 

Вы можете использовать в нижнем формате, исходное значение по умолчанию, начиная с 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 

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; 
  • Что означает «typedef void (* Something) ()» означает
  • Преобразование цели-c typedef в его эквивалент строки
  • uint8_t против символа без знака
  • массив фиксированной длины typedef
  • Почему «typdef struct {struct S * s; } S; ", содержащий указатель на компиляцию того же типа?
  • Переслать-объявить перечисление в Objective-C
  • Это хорошая идея для указателей typedef?
  • Форвардное объявление typedef в C ++
  • C ++ typedef интерпретация константных указателей
  • самореферентное определение структуры?
  • В чем разница между «typedef» и «use» в C ++ 11?
  • Interesting Posts

    Различия в сценариях bash между $ @ и $ *

    Как удалить «заблокированный» файл?

    Клиент службы WCF: текст типа контента / html; charset = utf-8 ответного сообщения не соответствует типу содержимого привязки

    Добавить UIView над всеми другими видами, включая StatusBar

    Прикрепить отладчик в C # к другому процессу

    Как создать файл .jar или экспортировать jar на IntelliJ (например, экспорт java-архива eclipse)

    Являются ли частные члены унаследованы в C #?

    Как заполнить фоновое изображение UIView

    Параллельная копия файла из одного источника в несколько целей?

    Привязать к переменной массива bash косвенно, динамически сконструированным именем переменной

    Как обрабатывать backPress с помощью fragmentа

    как получить идентификатор электронной почты из facebook sdk в приложениях для Android?

    Ошибка: Status {statusCode = DEVELOPER_ERROR, разрешение = null}

    Исходная политическая маршрутизация и NAT (DNAT / SNAT) aka Multi WANs на CentOS 5

    Нет доступного экземпляра типа

    Давайте будем гением компьютера.