enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
Например, как я могу сделать что-то вроде:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
Результирующий пример:
♠
♥
♦
♣
Ответы:
Swift 4.2+
Начиная с Swift 4.2 (с Xcode 10), просто добавьте соответствие протокола, чтобы
CaseIterable
получить выгодуallCases
. Чтобы добавить соответствие этого протокола, вам просто нужно написать куда-нибудь:Если перечисление принадлежит вам, вы можете указать соответствие непосредственно в декларации:
Затем следующий код выведет все возможные значения:
Совместимость с более ранними версиями Swift (3.x и 4.x)
Если вам требуется поддержка Swift 3.x или 4.0, вы можете имитировать реализацию Swift 4.2, добавив следующий код:
источник
String
, в отличие от существующего вопроса переполнения стека.Этот пост актуален здесь https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift
По сути, предлагаемое решение
источник
Enum.Values(typeof(FooEnum))
но оно будет представлено как метод расширения (например, map или redu).FooEnum.values() :: values(EnumType -> [EnumType])
Я сделал функцию полезности
iterateEnum()
для итерации случаев для произвольныхenum
типов.Вот пример использования:
Какие выводы:
Но это только для целей отладки или тестирования : это зависит от недокументированного поведения компилятора Swift1.1, поэтому используйте его на свой страх и риск.
Вот код:
Основная идея:
enum
, исключаяenum
s со связанными типами, является просто индексом случаев, когда количество случаев равно2...256
, равноUInt8
, когда257...65536
, этоUInt16
и так далее. Таким образом, это может бытьunsafeBitcast
из соответствующих целых типов без знака..hashValue
значений перечисления совпадает с индексом регистра..hashValue
о перечислении значения bitcasted от недопустимого индекса0
.Пересмотрен для Swift2 и реализован идеи кастинга из ответа @ Kametrixom :
Пересмотрен для Swift3:
Пересмотрен для Swift3.0.1:
источник
withUnsafePointer
withMemoryRebound
иpointee
прочее, то используйте это во что бы то ни стало. В противном случае я бы избежал этого.Другие решения работают, но все они делают предположения, например, о количестве возможных рангов и мастей, или о том, каким может быть первый и последний ранг. Правда, расположение колоды карт, вероятно, не изменится в обозримом будущем. В целом, однако, лучше писать код, который делает как можно меньше предположений. Мое решение:
Я добавил необработанный тип в
Suit
перечисление, так что я могу использоватьSuit(rawValue:)
для доступа кSuit
случаям:Ниже приведена реализация метода Карда
createDeck()
.init(rawValue:)
является неисправным инициализатором и возвращает необязательный. Развернув и проверив его значение в обоих операторах while, нет необходимости предполагать количествоRank
илиSuit
случаев:Вот как вызвать
createDeck
метод:источник
Suit
. Вы можете в этом примере, но упражнение предназначалось для того, чтобы заставить вас работать с тем, чтоenums
вам дали, как если бы они были из внешнего источника.Я наткнулся на биты и байты и создал расширение, которое позже обнаружил, что оно очень похоже на ответ @rintaro . Используется так:
Что примечательно, так это то, что его можно использовать для любого перечисления без соответствующих значений. Обратите внимание, что это не работает для перечислений, которые не имеют регистра.
Как и в ответе @rintaro , этот код использует базовое представление перечисления. Это представление не задокументировано и может измениться в будущем, что может его сломать. Я не рекомендую использовать это в производстве.
Код (Swift 2.2, Xcode 7.3.1, не работает на Xcode 10):
Код (Swift 3, Xcode 8.1, не работает на Xcode 10):
Понятия не имею, зачем мне это нужно
typealias
, но компилятор жалуется без этого.источник
withUnsafePointer
…pointee}
наwithUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } }
Вы можете перебирать перечисление путем реализации
ForwardIndexType
протокола.ForwardIndexType
Протокол требует , чтобы определитьsuccessor()
функцию пошаговых элементов.Итерация по открытому или закрытому диапазону (
..<
или...
) вызовет внутреннююsuccessor()
функцию, которая позволит вам написать это:источник
successor()
метод (первый вариант) устраняет необходимостьenum
иметь связанный тип. +1Эта проблема теперь намного проще. Вот мое решение Swift 4.2:
До 4.2:
Мне нравится это решение, которое я собрал после нахождения « Понимания списка в Swift ».
Он использует Int raw вместо Strings, но избегает ввода дважды, позволяет настраивать диапазоны и не жестко кодирует необработанные значения.
Это версия Swift 4 моего оригинального решения, но см. Улучшение 4.2 выше:
источник
В принципе, это можно сделать таким образом, если вы не используете необработанные присваивания значений для случаев enum:
источник
enum ItWontWorkForThisEnum {case a, b, c}
Если вы дадите enum необработанное значение Int, это значительно упростит зацикливание.
Например, вы можете использовать
anyGenerator
генератор, который может перечислять ваши значения:Тем не менее, это выглядит как довольно распространенный шаблон, не было бы неплохо, если бы мы могли сделать любой перечисляемый тип перечисления простым соответствием протоколу? Хорошо с Swift 2.0 и расширениями протокола, теперь мы можем!
Просто добавьте это в ваш проект:
Теперь каждый раз, когда вы создаете перечисление (если оно имеет необработанное значение Int), вы можете сделать его перечислимым, следуя протоколу:
Если ваши значения перечисления не начинаются с
0
(по умолчанию), переопределитеfirstRawValue
метод:Окончательный класс костюма, включая замену
simpleDescription
с более стандартным CustomStringConvertible протоколом , будет выглядеть следующим образом :Синтаксис Swift 3:
источник
Обновлено до Swift 2.2 +
Обновлен код до формы Swift 2.2 @ Kametrixom's answer
Для Swift 3.0+ (большое спасибо @Philip )
источник
Решение Swift 5:
источник
Я обнаружил, что
.allValues
много делаю по всему коду. Я наконец нашел способ просто соответствоватьIteratable
протоколу и иметьrawValues()
метод.источник
Xcode 10 с Swift 4.2
Назови это
Печать:
Старые версии
Для
enum
представленияInt
Назовите это так:
Печать:
Для
enum
представленияString
Назови это
Печать:
источник
РЕДАКТИРОВАТЬ: Swift Evolution Proposal SE-0194 Производная коллекция Enum Cases предлагает поэтапное решение этой проблемы. Мы видим это в Swift 4.2 и новее. Предложение также указывает на некоторые обходные пути , аналогичные тем, которые уже упоминались здесь, но, тем не менее, было бы интересно посмотреть.
Я также сохраню свой оригинальный пост для полноты картины.
Это еще один подход, основанный на ответе @ Peymmankh, адаптированный к Swift 3 .
источник
Как насчет этого?
источник
Вы можете попробовать перечислить, как это
источник
static var enumerate = [Mercury, Venus, Earth, Mars]
, что он является ответом на более низком уровне по сравнению с большинством проголосовавших ответов stackoverflow.com/a/24137319/1033581return [Mercury, Venus, Mars]
вместоreturn [Mercury, Venus, Earth, Mars]
return [.spades, .hearts, .clubs]
компилятор ничего не скажет, а затем, когда вы попытаетесь использовать его в коде, вы поймете[TestApp.Suit.spades, TestApp.Suit.hearts, TestApp.Suit.clubs]
- это было моей точкой зрения - если вы имеете дело с большим enum, и вы должны время от времени добавлять или удалять случаи, ваше решение подвержено ошибкам пропуска, в то время как текущий ответ, хотя и не является кратким, безопаснее.В Swift 3, когда есть базовое перечисление
rawValue
, вы можете реализоватьStrideable
протокол. Преимущества состоят в том, что массивы значений не создаются, как в некоторых других предложениях, и что работает стандартный цикл Swift «для», что создает приятный синтаксис.источник
Это решение обеспечивает правильный баланс удобочитаемости и удобства обслуживания.
источник
Извините, мой ответ был конкретным, как я использовал этот пост в том, что мне нужно было сделать. Для тех, кто наткнулся на этот вопрос, ищет способ найти случай в перечислении, вот способ сделать это (новое в Swift 2):
Редактировать: строчный camelCase теперь стандарт для значений перечисления Swift 3
Для тех, кто интересуется перечислением перечислений, ответы на этой странице, включающие статический var / let, содержащий массив всех значений перечисления, являются правильными. Последний пример кода Apple для tvOS содержит ту же самую технику.
При этом они должны встроить более удобный механизм в язык (Apple, вы слушаете?)!
источник
Эксперимент был: ЭКСПЕРИМЕНТ
Добавьте метод к Карте, который создает полную колоду карт, с одной картой каждой комбинации ранга и масти.
Поэтому, не изменяя или не улучшая данный код, кроме добавления метода (и не используя материал, который еще не изучен), я придумал это решение:
источник
Вот метод, который я использую для итерации
enum
и предоставления нескольких типов значений из одногоenum
Это вывод:
Число ноль по-французски: zéro, испанский: cero, japanese: nuru
Число по-французски: un, испанский: uno, japanese: ichi
Номер два по-французски: deux, испанский: dos, японский: ni
Номер три по-французски : trois, испанский: tres, japanese: san
Номер четыре на французском: quatre, испанский: cuatro, japanese: shi
Номер пять на французском: cinq, испанский: cinco, japanese: go
Номер шесть на французском: шесть, испанский: seis, японский: roku
Число семь на французском: сент, испанский: сите, японский: shichi
Всего 8 случаев
сиэтэ по японски: shichi
ОБНОВИТЬ
Недавно я создал протокол для обработки перечисления. Протокол требует перечисления с необработанным значением Int:
источник
Это похоже на хак, но если вы используете необработанные значения, вы можете сделать что-то вроде этого
источник
Пока имею дело с
Swift 2.0
вот моим предложением:Я добавил необработанный тип в
Suit
enum
тогда:
источник
Как с @Kametrixom ответ здесь , я считаю , возвращая массив будет лучше , чем возвращение AnySequence, так как вы можете иметь доступ ко всему лакомство массива, такие как подсчет, и т.д.
Вот переписать:
источник
Другое решение:
источник
Это довольно старый пост из Swift 2.0. Теперь здесь есть несколько лучших решений, использующих новые функции swift 3.0: перебор Enum в Swift 3.0
И в этом вопросе есть решение, которое использует новую функцию (еще не выпущенную, когда я пишу это редактирование) Swift 4.2: Как я могу получить счет перечисления Swift?
В этой ветке есть много хороших решений, но некоторые из них очень сложны. Мне нравится максимально упрощать. Вот решение, которое может или не может работать для разных нужд, но я думаю, что оно работает хорошо в большинстве случаев:
Итерировать:
источник
Перечни есть
toRaw()
иfromRaw()
методы. Поэтому, если ваше необработанное значение равноInt
, вы можете перебирать от первого до последнегоenum
:Одна проблема заключается в том, что вам нужно проверить дополнительные значения перед запуском
simpleDescription
метода, поэтомуconvertedSuit
сначала мы устанавливаем наше значение, а затем устанавливаем константуconvertedSuit.simpleDescription()
источник
Вот мой предложенный подход. Это не совсем удовлетворительно (я очень новичок в Swift и ООП!), Но, возможно, кто-то может улучшить это. Идея состоит в том, чтобы каждое перечисление предоставляло собственную информацию о диапазоне
.first
и.last
свойствах. Он добавляет всего две строки кода к каждому перечислению: все еще немного жестко, но, по крайней мере, он не дублирует весь набор. Это требует измененияSuit
перечисления, чтобы быть Int, какRank
enum, а не нетипизированным.Вместо того, чтобы отражать все решение, вот код, который я добавил в
.
enum, где-то после операторов case (Suit
enum похож):и цикл, который я использовал для построения колоды в виде массива String. (В определении проблемы не указано, как должна быть структурирована колода.)
Это неудовлетворительно, потому что свойства связаны с элементом, а не с перечислением. Но это добавляет ясности в циклы for. Я бы хотел это сказать
Rank.first
вместоRank.Ace.first
. Это работает (с любым элементом), но это некрасиво. Может кто-нибудь показать, как поднять это до уровня enum?И чтобы это сработало, я поднял
createDeck
метод из структуры Card. Я не мог понять, как получить массив [String], возвращаемый из этой структуры, и это все равно кажется плохим местом для размещения такого метода.источник
Я сделал это, используя свойство computed, которое возвращает массив всех значений (благодаря этому посту http://natecook.com/blog/2014/10/loopy-random-enum-ideas/ ). Однако он также использует int raw-values, но мне не нужно повторять все члены перечисления в отдельном свойстве.
ОБНОВЛЕНИЕ Xcode 6.1 немного изменил способ получения члена enum
rawValue
, поэтому я исправил листинг. Также исправлена небольшая ошибка с неправильным первымrawValue
.источник
Исходя из ответа Рика: это в 5 раз быстрее
источник
Count
случая нарушит исчерпывающиеswitch
реализации иCaseIterable
соответствие.