enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
Na przykład, jak mogę zrobić coś takiego:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
Wynikowy przykład:
♠
♥
♦
♣
Odpowiedzi:
Swift 4.2+
Począwszy od Swift 4.2 (z Xcode 10), po prostu dodaj zgodność protokołu,
CaseIterable
aby skorzystaćallCases
. Aby dodać tę zgodność protokołu, wystarczy gdzieś napisać:Jeśli wyliczenie jest twoje, możesz określić zgodność bezpośrednio w deklaracji:
Następnie poniższy kod wydrukuje wszystkie możliwe wartości:
Kompatybilność z wcześniejszymi wersjami Swift (3.x i 4.x)
Jeśli potrzebujesz obsługi Swift 3.x lub 4.0, możesz naśladować implementację Swift 4.2, dodając następujący kod:
źródło
String
, w przeciwieństwie do obecnego pytania dotyczącego przepełnienia stosu.Ten post jest tutaj istotny https://www.swift-studies.com/blog/2014/6/10/enumerating-enums-in-swift
Zasadniczo proponowane rozwiązanie to
źródło
Enum.Values(typeof(FooEnum))
ale ujawniono jako metodę rozszerzenia (np. Mapuj lub zmniejsz).FooEnum.values() :: values(EnumType -> [EnumType])
Stworzyłem funkcję użyteczną
iterateEnum()
do iterowania spraw dla dowolnychenum
typów.Oto przykładowe użycie:
Które wyjścia:
Ale służy to tylko do debugowania lub testowania : zależy to od kilku nieudokumentowanych zachowań kompilatora Swift1.1, więc używaj go na własne ryzyko.
Oto kod:
Podstawową ideą jest:
enum
, wyłączającenum
s z powiązanymi typami, jest tylko indeksem przypadków, gdy liczba przypadków jest2...256
identyczna zUInt8
, kiedy257...65536
, toUInt16
i tak dalej. Może więc pochodzićunsafeBitcast
z odpowiadających typów całkowitych bez znaku..hashValue
wartości wyliczeniowych jest taki sam jak indeks sprawy..hashValue
z wartości wyliczeniowych bitcastowanych z niepoprawnego indeksu to0
.Zmieniono dla Swift2 i wprowadzono pomysły rzutowania z odpowiedzi @ Kametrixom :
Zmieniono dla Swift3:
Zmieniono dla Swift3.0.1:
źródło
withUnsafePointer
withMemoryRebound
i innychpointee
rzeczy, użyj tego za wszelką cenę. W przeciwnym razie uniknęłbym tego.Inne rozwiązania działają, ale wszystkie przyjmują na przykład liczbę możliwych rang i kolorów lub jaka może być pierwsza i ostatnia ranga. To prawda, że układ talii kart prawdopodobnie nie zmieni się znacząco w dającej się przewidzieć przyszłości. Ogólnie jednak fajniej jest pisać kod, który przyjmuje możliwie najmniejsze założenia. Moje rozwiązanie:
Dodałem surowy typ do
Suit
wyliczenia, dzięki czemu mogę uzyskaćSuit(rawValue:)
dostęp doSuit
skrzynek:Poniżej implementacja metody Karty
createDeck()
.init(rawValue:)
jest inicjalizatorem awaryjnym i zwraca opcjonalny. Po rozpakowaniu i sprawdzeniu jego wartości w obu instrukcjach while nie trzeba przyjmować liczbyRank
lubSuit
przypadków:Oto jak wywołać
createDeck
metodę:źródło
Suit
. Możesz w tym przykładzie, ale ćwiczenie miało zmusić cię do pracy z tym,enums
co otrzymałeś, jakby pochodziło z zewnętrznego źródła.Potknąłem się w bitach i bajtach i stworzyłem rozszerzenie, które później odkryłem, działa bardzo podobnie do odpowiedzi @rintaro . Używa się go w następujący sposób:
Niezwykłe jest to, że można go stosować na dowolnym wyliczeniu bez powiązanych wartości. Zauważ, że to nie działa dla wyliczeń, które nie mają spraw.
Podobnie jak w przypadku odpowiedzi @rintaro , ten kod wykorzystuje reprezentację wyliczenia. Ta reprezentacja nie jest udokumentowana i może ulec zmianie w przyszłości, co może ją zepsuć. Nie polecam wykorzystania tego w produkcji.
Kod (Swift 2.2, Xcode 7.3.1, nie działa na Xcode 10):
Kod (Swift 3, Xcode 8.1, nie działa na Xcode 10):
Nie mam pojęcia, dlaczego potrzebuję
typealias
, ale kompilator narzeka bez tego.źródło
withUnsafePointer
…pointee}
przezwithUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } }
Możesz iterować przez wyliczanie, implementując
ForwardIndexType
protokół.ForwardIndexType
Protokół wymaga, aby zdefiniowaćsuccessor()
funkcję kroku przez elementy.Iteracja w zakresie otwartym lub zamkniętym (
..<
lub...
) wywoła wewnętrzniesuccessor()
funkcję, która pozwala napisać:źródło
successor()
metoda (pierwsza opcja) wyeliminuje potrzebęenum
posiadania powiązanego typu. +1Ten problem jest teraz znacznie łatwiejszy. Oto moje rozwiązanie Swift 4.2:
Przed 4.2:
Podoba mi się to rozwiązanie, które połączyłem po znalezieniu „ Listy ze zrozumieniem w Swift ”.
Używa surowych Int zamiast Ciągów, ale unika podwójnego pisania, pozwala dostosowywać zakresy i nie zapisuje surowych wartości kodu.
To jest wersja Swift 4 mojego oryginalnego rozwiązania, ale zobacz ulepszenie 4.2 powyżej:
źródło
Zasadniczo można to zrobić w ten sposób, zakładając, że nie używasz przypisania wartości surowych dla przypadków enum:
źródło
enum ItWontWorkForThisEnum {case a, b, c}
Jeśli podasz enum surową wartość Int znacznie ułatwi zapętlenie.
Na przykład możesz użyć,
anyGenerator
aby uzyskać generator, który może wyliczyć wszystkie wartości:Wygląda to jednak na dość powszechny wzorzec, czy nie byłoby miło, gdybyśmy mogli wyliczyć dowolny typ wyliczeniowy, po prostu dostosowując się do protokołu? Dobrze z Swift 2.0 i rozszerzeniami protokołu, teraz możemy!
Po prostu dodaj to do swojego projektu:
Teraz za każdym razem, gdy tworzysz wyliczenie (o ile ma wartość surową Int), możesz uczynić ją wyliczalną, postępując zgodnie z protokołem:
Jeśli twoje wartości wyliczeniowe nie zaczynają się od
0
(domyślne), zastąpfirstRawValue
metodę:Ostateczna klasa garnitur, włącznie z wymianą
simpleDescription
z bardziej standardowym protokołem CustomStringConvertible będzie wyglądać następująco:Składnia Swift 3:
źródło
Zaktualizowano do Swift 2.2 +
Zaktualizowano kod do formularza Swift 2.2 z odpowiedzi Kametrixom
Dla Swift 3.0+ ( wielkie dzięki dla @Philip )
źródło
Rozwiązanie Swift 5:
źródło
Odkryłem, że robię
.allValues
dużo w całym moim kodzie. W końcu wymyśliłem sposób, aby po prostu dostosować się doIteratable
protokołu i miećrawValues()
metodę.źródło
Xcode 10 z Swift 4.2
Nazwać
Wydruki:
starsza wersja
Do
enum
reprezentowaniaInt
Nazwij to tak:
Wydruki:
Do
enum
reprezentowaniaString
Nazwać
Wydruki:
źródło
EDYCJA: Swift Evolution Wniosek SE-0194 Zbiór skrzynek Enum proponuje jednoznaczne rozwiązanie tego problemu. Widzimy to w Swift 4.2 i nowszych. Wniosek wskazuje również na niektóre obejścia podobne do już wspomnianych tutaj, ale mimo wszystko warto je zobaczyć.
Zachowam również mój oryginalny post ze względu na kompletność.
Jest to kolejne podejście oparte na odpowiedzi @ Peymmankh, dostosowane do Swift 3 .
źródło
Co powiesz na to?
źródło
Możesz spróbować wyliczyć w ten sposób
źródło
static var enumerate = [Mercury, Venus, Earth, Mars]
, że jest to odpowiedź słaba w porównaniu do większości głosowanych odpowiedzi stackoverflow.com/a/24137319/1033581return [Mercury, Venus, Mars]
zamiastreturn [Mercury, Venus, Earth, Mars]
return [.spades, .hearts, .clubs]
kompilatorem nic nie powiesz, a następnie, gdy spróbujesz użyć jej w kodzie, otrzymasz[TestApp.Suit.spades, TestApp.Suit.hearts, TestApp.Suit.clubs]
- o to mi chodziło - że jeśli masz do czynienia z dużym Wylicz i musisz od czasu do czasu dodawać lub usuwać przypadki, twoje rozwiązanie jest podatne na błędy pominięcia, podczas gdy bieżąca odpowiedź, choć nie jest zwięzła, jest bezpieczniejsza.W Swift 3, gdy ma wyliczenie bazowe
rawValue
, możesz zaimplementowaćStrideable
protokół. Zaletą jest to, że nie są tworzone tablice wartości jak w niektórych innych sugestiach i że działa standardowa pętla Swift „for in”, co stanowi niezłą składnię.źródło
To rozwiązanie zapewnia właściwą równowagę czytelności i łatwości konserwacji.
źródło
Przepraszam, moja odpowiedź była konkretna dla tego, jak wykorzystałem ten post w tym, co musiałem zrobić. Dla tych, którzy natkną się na to pytanie, szukając sposobu na znalezienie przypadku w wyliczeniu, jest to sposób, aby to zrobić (nowość w Swift 2):
Edycja: camelCase z małymi literami jest teraz standardem dla wartości wyliczeniowych Swift 3
Dla tych, którzy zastanawiają się nad wyliczaniem w wyliczeniu, odpowiedzi podane na tej stronie, które obejmują statyczny var / let zawierający tablicę wszystkich wartości wyliczeniowych, są poprawne. Najnowszy przykładowy kod Apple dla tvOS zawiera dokładnie tę samą technikę.
To powiedziawszy, powinni zbudować bardziej wygodny mechanizm języka (Apple, słuchasz?)!
źródło
Eksperyment był następujący: DOŚWIADCZENIE
Dodaj metodę do karty, która tworzy pełną talię kart, z jedną kartą dla każdej kombinacji rangi i koloru.
Więc bez modyfikowania lub ulepszania danego kodu poza dodaniem metody (i bez użycia rzeczy, których jeszcze nie nauczono), wymyśliłem to rozwiązanie:
źródło
Oto metoda, której używam zarówno do iteracji, jak
enum
i zapewniania wielu typów wartości z jednegoenum
To jest wynik:
Liczba zero po francusku: zéro, hiszpański: cero, japoński: nuru
Liczba jeden po francusku: un, hiszpański: uno, japoński: ichi
Liczba dwa po francusku: deux, hiszpański: dos, japoński: ni
Liczba trzy po francusku : trois, hiszpański: tres, japoński: san
Numer cztery po francusku: quatre, hiszpański: cuatro, japoński: shi
Numer pięć po francusku: cinq, hiszpański: cinco, japoński: go
Numer sześć po francusku: sześć, hiszpański: seis, japanese: roku
Number Seven po francusku: sept, spanish: siete, japanese: shichi
Łącznie 8 przypadków
siete po japońsku: shichi
AKTUALIZACJA
Niedawno utworzyłem protokół do obsługi wyliczenia. Protokół wymaga wyliczenia o wartości surowej Int:
źródło
To wygląda na włamanie, ale jeśli używasz surowych wartości, możesz zrobić coś takiego
źródło
Podczas zajmowania się
Swift 2.0
tutaj jest moja sugestia:Dodałem typ surowy do
Suit
enum
następnie:
źródło
Tak jak w przypadku @Kametrixom odpowiedź tutaj uważam, że zwrócenie tablicy byłoby lepsze niż zwrócenie AnySequence, ponieważ możesz mieć dostęp do wszystkich korzyści Array, takich jak liczba itp.
Oto przepis:
źródło
Inne rozwiązanie:
źródło
To dość stary post z Swift 2.0. Istnieją teraz lepsze rozwiązania, które wykorzystują nowsze funkcje swift 3.0: Iteracja przez Enum w Swift 3.0
I w tym pytaniu istnieje rozwiązanie, które wykorzystuje nową funkcję (jeszcze nie wydanego, gdy piszę tę edycję) Swift 4.2: Jak uzyskać liczbę wyliczeń Swift?
W tym wątku jest wiele dobrych rozwiązań, a niektóre z nich są jednak bardzo skomplikowane. Lubię maksymalnie uprościć. Oto rozwiązanie, które może, ale nie musi, działać dla różnych potrzeb, ale myślę, że działa dobrze w większości przypadków:
Aby iterować:
źródło
Wyliczenia mają
toRaw()
ifromRaw()
metody. Jeśli więc twoja pierwotna wartość to anInt
, możesz iterować od pierwszego do ostatniegoenum
:Jedną z nich jest to, że musisz przetestować opcjonalne wartości przed uruchomieniem
simpleDescription
metody, więcconvertedSuit
najpierw ustawiamy naszą wartość, a następnie ustawiamy stałą naconvertedSuit.simpleDescription()
źródło
Oto moje sugerowane podejście. Nie jest całkowicie zadowalający (jestem nowy w Swift i OOP!), Ale może ktoś może to udoskonalić. Chodzi o to, aby każde wyliczenie zapewniało swój własny zakres informacji
.first
i.last
właściwości. Dodaje tylko dwa wiersze kodu do każdego wyliczenia: wciąż trochę zakodowane, ale przynajmniej nie powiela całego zestawu. Wymaga zmodyfikowaniaSuit
wyliczenia tak, aby było Int, tak jakRank
wyliczenie, zamiast bez typu.Zamiast powtórzyć całe rozwiązanie, oto kod, który dodałem do
.
wyliczenia, gdzieś po instrukcji case (Suit
wyliczenie jest podobne):i pętlę, której użyłem do zbudowania talii jako tablicy String. (Definicja problemu nie określała, w jaki sposób miała być zbudowana talia).
Jest to niezadowalające, ponieważ właściwości są powiązane raczej z elementem niż z wyliczeniem. Ale dodaje jasności pętlom „za”. Chciałbym to powiedzieć
Rank.first
zamiastRank.Ace.first
. Działa (z dowolnym elementem), ale jest brzydki. Czy ktoś może pokazać, jak podnieść to do poziomu wyliczenia?Aby to zadziałało, podniosłem
createDeck
metodę z struktury karty. Nie mogłem wymyślić, jak uzyskać tablicę [String] z tej struktury, i wydaje się to złe miejsce na zastosowanie takiej metody.źródło
Zrobiłem to za pomocą obliczonej właściwości, która zwraca tablicę wszystkich wartości (dzięki temu postowi http://natecook.com/blog/2014/10/loopy-random-enum-ideas/ ). Jednak używa również int surowych wartości, ale nie muszę powtarzać wszystkich elementów wyliczenia w osobnej właściwości.
AKTUALIZACJA Xcode 6.1 zmienił nieco sposób uzyskiwania członka enum
rawValue
, więc naprawiłem listę. Naprawiono również mały błąd z niewłaściwym pierwszymrawValue
.źródło
Na podstawie odpowiedzi Ricka: jest to 5 razy szybciej
źródło
Count
skrzynki złamie wyczerpująceswitch
implementacje iCaseIterable
zgodność.