Jak uzyskać liczbę szybkiego wyliczenia?

Odpowiedzi:

173

Począwszy od Swift 4.2 (Xcode 10) możesz zadeklarować zgodność z CaseIterableprotokołem, działa to dla wszystkich wyliczeń bez powiązanych wartości:

enum Stuff: CaseIterable {
    case first
    case second
    case third
    case forth
}

Liczba przypadków jest teraz po prostu uzyskiwana za pomocą

print(Stuff.allCases.count) // 4

Aby uzyskać więcej informacji, zobacz

Martin R.
źródło
1
W najnowszej wersji programu swift błąd zgłaszania „Typ„ DAFFlow ”nie jest zgodny z protokołem„ RawRepresentable ””. Dlaczego zmuszanie mnie do tego? Dowolny pomysł?
Satyam
@Satyam: Co to jest DAFFlow?
Martin R
przepraszam, zapomniałem wspomnieć, że „DAFFlow” jest prostym wyliczeniem, które nie dziedziczy po żadnym innym protokole
Satyam
1
Jest to najlepsze rozwiązanie, ale dla jasności - programiści Apple będą mogli zacząć używać go dopiero, gdy Xcode 10 (a więc Swift 4.2) wyjdzie z wersji beta (prawdopodobnie około 14 września 2018 r.).
JosephH
1
@DaniSpringer: Znajdziesz drastyczne szczegóły w github.com/apple/swift-evolution/blob/master/proposals/... . Ale zwykle nie potrzebujesz tego typu jawnie, ze względu na automatyczne wnioskowanie o typie kompilatora.
Martin R
143

Mam wpis na blogu, który zawiera bardziej szczegółowe informacje na ten temat, ale dopóki surowy typ wyliczenia jest liczbą całkowitą, możesz dodać liczbę w ten sposób:

enum Reindeer: Int {
    case Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen
    case Rudolph

    static let count: Int = {
        var max: Int = 0
        while let _ = Reindeer(rawValue: max) { max += 1 }
        return max
    }()
}
Nate Cook
źródło
16
To miłe, ponieważ nie musisz kodować wartości na stałe, spowoduje to utworzenie każdej wartości wyliczenia za każdym razem, gdy zostanie wywołana. To jest O (n) zamiast O (1). :(
Code Commander
4
To dobre rozwiązanie dla ciągłego Int. Wolę niewielką modyfikację. Przekształć właściwość static count w metodę static countCases () i przypisz ją do stałej static caseCount, która jest leniwa i poprawia wydajność przy wielokrotnych wywołaniach.
Tom Pelaia,
2
@ShamsAhmed: Konwertuje obliczony var na statyczny.
Nate Cook
3
Co jeśli przegapisz jakąś wartość w wyliczeniu? na przykład case A=1, B=3?
Sasho,
2
Istnieją dwa założenia oprócz enumposiadania Intsurowej wartości, o której zapomniałeś wspomnieć: Szybkie wyliczanie z Int surowymi wartościami nie muszą zaczynać się od 0 (chociaż jest to zachowanie domyślne), a ich surowe wartości mogą być dowolne, nie mają zwiększać o 1 (nawet jeśli jest to zachowanie domyślne).
Dávid Pásztor
90

Aktualizacja Xcode 10

Przyjęcie CaseIterableprotokołu w wyliczeniu, zapewnia on allCaseswłaściwość statyczną, która zawiera wszystkie przypadki wyliczania jako Collection. Wystarczy użyć jego countwłaściwości, aby dowiedzieć się, ile przypadków ma wyliczenie.

Zobacz przykład Martina (i głosuj raczej na jego odpowiedzi niż moje)


Ostrzeżenie : poniższa metoda wydaje się już nie działać.

Nie znam żadnej ogólnej metody liczenia liczby przypadków wyliczania. Zauważyłem jednak, że hashValuewłaściwość przypadków wyliczeniowych jest przyrostowa, zaczynając od zera, i według kolejności określonej przez porządek, w którym przypadki są zadeklarowane. Tak więc skrót ostatniego wyliczenia plus jeden odpowiada liczbie przypadków.

Na przykład z tym wyliczeniem:

enum Test {
    case ONE
    case TWO
    case THREE
    case FOUR

    static var count: Int { return Test.FOUR.hashValue + 1}
}

count zwraca 4.

Nie mogę powiedzieć, czy to reguła, czy zmieni się ona w przyszłości, więc używaj na własne ryzyko :)

Antonio
źródło
48
Żyj według funkcji nieudokumentowanej, giń według funkcji nieudokumentowanej. Lubię to!
Nate Cook
9
Tak naprawdę nie powinniśmy polegać na hashValuestych rzeczach; wiemy tylko, że jest to jakaś losowa unikalna wartość - może w przyszłości bardzo łatwo ulec zmianie w zależności od szczegółów implementacyjnych kompilatora; ale ogólnie niepokojący jest brak wbudowanej funkcji liczenia.
Zorayr
16
Jeśli nie przeszkadza wyraźnie ustalone case ONE = 0, można następnie wymienić hashValuez rawValue.
Kevin Qi,
3
chodzi tu o użycie nieudokumentowanej właściwości hashValue, więc moją sugestią jest użycie udokumentowanej właściwości rawValue.
Kevin Qi,
7
Już zakodowałeś fakt, że stała jest najwyższą wartością, Lepiej i bezpieczniej jest po prostu użyć czegoś takiego static var count = 4niż pozostawić swoje przeznaczenie w losie przyszłych wdrożeń Swift
Dale
72

Definiuję protokół wielokrotnego użytku, który automatycznie wykonuje licznik spraw na podstawie podejścia opublikowanego przez Nate Cook.

protocol CaseCountable {
    static var caseCount: Int { get }
}

extension CaseCountable where Self: RawRepresentable, Self.RawValue == Int {
    internal static var caseCount: Int {
        var count = 0
        while let _ = Self(rawValue: count) {
            count += 1
        }
        return count
    }
}

Następnie mogę ponownie użyć tego protokołu, na przykład w następujący sposób:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)
Tom Pelaia
źródło
1
Ładna i elegancka, powinna być przyjęta odpowiedź IMHO
shannoga,
1
może lepiej jest zmienić count++na, count+=1ponieważ ++notacja zostanie usunięta w Swift 3
Aladin,
1
nie można tego samego zrobić tylko z static var caseCount: Int { get }? skąd ta potrzeba static func?
pxpgraphics
Co jeśli przegapisz jakąś wartość w wyliczeniu? na przykład case A=1, B=3?
Sasho
1
@Sasho, to nie będzie działać. To wymaga, aby twoje sprawy zaczęły się od 0i nie miały żadnych luk.
NRitH
35

Utwórz statyczną tablicę allValues, jak pokazano w tej odpowiedzi

enum ProductCategory : String {
     case Washers = "washers", Dryers = "dryers", Toasters = "toasters"

     static let allValues = [Washers, Dryers, Toasters]
}

...

let count = ProductCategory.allValues.count

Jest to również pomocne, gdy chcesz wyliczyć wartości i działa dla wszystkich typów Enum

david72
źródło
Chociaż nie jest tak elegancki jak rozwiązanie rozszerzeń i bardzo ręczny, uważam, że jest to najbardziej przydatne, ponieważ oferuje znacznie więcej niż liczenie. Daje ci porządek wartości i listę wszystkich wartości.
Nader Eloshaiker,
2
Możesz także dodać liczbę do wyliczenia, wykonując static let count = allValues.count. W allValuesrazie potrzeby możesz ustawić prywatny.
ThomasW
15

Jeśli implementacja nie ma nic przeciwko używaniu wyliczeń całkowitych, możesz dodać dodatkową wartość członka wywoływaną w Countcelu reprezentowania liczby członków w wyliczeniu - patrz przykład poniżej:

enum TableViewSections : Int {
  case Watchlist
  case AddButton
  case Count
}

Teraz możesz uzyskać liczbę członków w wyliczeniu, dzwoniąc, TableViewSections.Count.rawValueco zwróci 2 dla powyższego przykładu.

Podczas obsługi wyliczenia w instrukcji switch upewnij się, że rzuciłeś błąd asercji, gdy napotkasz Countczłonka, którego się nie spodziewasz:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let currentSection: TableViewSections = TableViewSections.init(rawValue:section)!
  switch(currentSection) {
  case .Watchlist:
    return watchlist.count
  case .AddButton:
    return 1
  case .Count:
    assert(false, "Invalid table view section!")
  }
}
Zorayr
źródło
Podoba mi się to rozwiązanie, ponieważ automatycznie zmienia liczbę przy dodawaniu większej liczby wartości wyliczania. Należy jednak pamiętać, że działa to tylko wtedy, gdy wartości surowe wyliczenia zaczynają się od 0
dołącza
2
Zgadzam się, istnieją dwa ograniczenia: musi być wyliczeniem liczby całkowitej i musi zaczynać się od zera i kontynuować przyrostowo.
Zorayr
3
Myślałem, że
sednem mocniejszych wyliczeń
14

Ten rodzaj funkcji może zwrócić liczbę twojego wyliczenia.

Swift 2 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(&i) { UnsafePointer<T>($0).memory }).hashValue != 0 {
        i += 1
    }
    return i
}

Swift 3 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
   var i = 1
   while (withUnsafePointer(to: &i, {
      return $0.withMemoryRebound(to: T.self, capacity: 1, { return $0.pointee })
   }).hashValue != 0) {
      i += 1
   }
      return i
   }
Matthieu Riegler
źródło
3
To już nie działa w Swift 3. Próbowanie wypracować poprawną implementację, ale nadchodzi puste
Cody Winton
Debugowanie będzie bardzo trudne, jeśli adres pamięci bezpośrednio przylegający do końca enumjest również Hashable tego samego typu.
NRitH
10

Wyliczanie ciągów z indeksem

enum eEventTabType : String {
    case Search     = "SEARCH"
    case Inbox      = "INBOX"
    case Accepted   = "ACCEPTED"
    case Saved      = "SAVED"
    case Declined   = "DECLINED"
    case Organized  = "ORGANIZED"

    static let allValues = [Search, Inbox, Accepted, Saved, Declined, Organized]
    var index : Int {
       return eEventTabType.allValues.indexOf(self)!
    }
}

liczyć: eEventTabType.allValues.count

indeks: objeEventTabType.index

Cieszyć się :)

kalpesh jetani
źródło
10

Hej wszystkim, a co z testami jednostkowymi?

func testEnumCountIsEqualToNumberOfItemsInEnum() {

    var max: Int = 0
    while let _ = Test(rawValue: max) { max += 1 }

    XCTAssert(max == Test.count)
}

W połączeniu z rozwiązaniem Antonio:

enum Test {

    case one
    case two
    case three
    case four

    static var count: Int { return Test.four.hashValue + 1}
}

w głównym kodzie daje O (1) plus dostajesz test negatywny, jeśli ktoś doda przypadek wyliczenia fivei nie zaktualizuje implementacji count.

buildsucceeded
źródło
7

Ta funkcja opiera się na 2 nieudokumentowanych bieżących zachowaniach (Swift 1.1) enum:

  • Układ pamięci enumjest tylko indeksem case. Jeśli liczba przypadków wynosi od 2 do 256, jest to UInt8.
  • Jeśli enumrzutowano bit z niepoprawnego indeksu wielkości liter, hashValueto jest0

Korzystaj więc na własne ryzyko :)

func enumCaseCount<T:Hashable>(t:T.Type) -> Int {
    switch sizeof(t) {
    case 0:
        return 1
    case 1:
        for i in 2..<256 {
            if unsafeBitCast(UInt8(i), t).hashValue == 0 {
                return i
            }
        }
        return 256
    case 2:
        for i in 257..<65536 {
            if unsafeBitCast(UInt16(i), t).hashValue == 0 {
                return i
            }
        }
        return 65536
    default:
        fatalError("too many")
    }
}

Stosowanie:

enum Foo:String {
    case C000 = "foo"
    case C001 = "bar"
    case C002 = "baz"
}
enumCaseCount(Foo) // -> 3
rintaro
źródło
W wersji i aplikacji adhoc ulegnie
awarii
Działa to w symulatorze, ale nie na prawdziwym urządzeniu 64-bitowym.
Daniel Nord
5

Napisałem proste rozszerzenie, które daje wszystkim wyliczeniom, w których surową wartością jest liczba całkowita, countwłaściwość:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

Niestety daje countwłaściwość OptionSetTypetam, gdzie nie będzie działać poprawnie, więc oto inna wersja, która wymaga jawnej zgodności z CaseCountableprotokołem dla każdego wyliczenia, które przypadki chcesz policzyć:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

Jest bardzo podobny do podejścia opublikowanego przez Toma Pelaia, ale działa ze wszystkimi typami liczb całkowitych.

bzz
źródło
4

Oczywiście nie jest dynamiczny, ale do wielu zastosowań możesz sobie poradzić dzięki statycznemu var dodanemu do twojego Enum

static var count: Int{ return 7 }

a następnie użyj go jako EnumName.count

Ian Dundas
źródło
3
enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

LUB

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

* W Swift 4.2 (Xcode 10) można używać:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3
Lê Cường
źródło
2

W moim przypadku użycia w bazie kodu, w której wiele osób może dodawać klucze do wyliczenia, a wszystkie te przypadki powinny być dostępne we właściwości allKeys, ważne jest, aby wszystkie klucze były sprawdzane względem kluczy w tym wyliczeniu. Ma to na celu uniknięcie sytuacji, gdy ktoś zapomni dodać swój klucz do listy wszystkich kluczy. Dopasowanie liczby tablicy allKeys (najpierw utworzonej jako zestaw, aby uniknąć duplikatów) do liczby kluczy w wyliczeniu zapewnia, że ​​wszystkie są obecne.

Niektóre z powyższych odpowiedzi pokazują sposób osiągnięcia tego w Swift 2, ale żadna nie działa w Swift 3 . Oto sformatowana wersja Swift 3 :

static func enumCount<T: Hashable>(_ t: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(to: &i) {
      $0.withMemoryRebound(to:t.self, capacity:1) { $0.pointee.hashValue != 0 }
    }) {
      i += 1
    }
    return i
}

static var allKeys: [YourEnumTypeHere] {
    var enumSize = enumCount(YourEnumTypeHere.self)

    let keys: Set<YourEnumTypeHere> = [.all, .your, .cases, .here]
    guard keys.count == enumSize else {
       fatalError("Missmatch between allKeys(\(keys.count)) and actual keys(\(enumSize)) in enum.")
    }
    return Array(keys)
}

W zależności od przypadku użycia możesz po prostu uruchomić test w fazie rozwoju, aby uniknąć narzutu związanego z używaniem wszystkich klawiszy na każde żądanie

Chris Mitchelmore
źródło
2

Dlaczego sprawiasz, że wszystko jest tak skomplikowane? Najprostszym licznikiem Int enum jest dodanie:

case Count

Na końcu. I ... altówka - teraz masz liczyć - szybko i prosto

Dimitar Marinov
źródło
1
To a) dodaje obcy przypadek wyliczenia ib) nie będzie działać, jeśli typ surowy wyliczenia jest inny niż Int.
Robert Atkins
To właściwie nie jest zła odpowiedź. Jednak, podobnie jak powyższa odpowiedź @Toma Pelaia, wymaga ona surowych wartości, aby zaczęły się od 0i nie miały żadnych przerw w sekwencji.
NRitH
1

Jeśli nie chcesz opierać kodu na ostatnim wyliczeniu, możesz utworzyć tę funkcję w swoim wyliczeniu.

func getNumberOfItems() -> Int {
    var i:Int = 0
    var exit:Bool = false
    while !exit {
        if let menuIndex = MenuIndex(rawValue: i) {
            i++
        }else{
            exit = true
        }
    }
    return i
}
Gabriel Araujo
źródło
1

Wersja Swift 3 działająca z Intwyliczeniami typów:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue == Int {
    static var count: RawValue {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) { i += 1 }
        return i
    }
}

Kredyty: Na podstawie odpowiedzi Bzz i Nate Cook.

Rodzajowy IntegerType(w Swift 3 przemianowany na Integer) nie jest obsługiwany, ponieważ jest to mocno rozdrobniony typ ogólny, który nie ma wielu funkcji. successornie jest już dostępny w Swift 3.

Pamiętaj, że komentarz od Code Commander do odpowiedzi Nate Cooks jest nadal aktualny:

To miłe, ponieważ nie musisz kodować wartości na stałe, spowoduje to utworzenie każdej wartości wyliczenia za każdym razem, gdy zostanie wywołana. To jest O (n) zamiast O (1).

O ile wiem, obecnie nie ma możliwości obejścia tego problemu jako rozszerzenia protokołu (i braku implementacji w każdym wyliczeniu, jak to zrobił Nate Cook) z powodu statycznych właściwości przechowywanych, które nie są obsługiwane w typach ogólnych.

W każdym razie dla małych wyliczeń nie powinno to stanowić problemu. Typowy przypadek użycia byłby section.countdla UITableViewsjak już wspomniano przez Zorayr.

Frederik Winkelsdorf
źródło
1

Rozszerzając odpowiedź Matthieu Rieglera, jest to rozwiązanie dla Swift 3, które nie wymaga użycia ogólnych, i można je łatwo wywołać za pomocą typu wyliczeniowego z EnumType.elementsCount:

extension RawRepresentable where Self: Hashable {

    // Returns the number of elements in a RawRepresentable data structure
    static var elementsCount: Int {
        var i = 1
        while (withUnsafePointer(to: &i, {
            return $0.withMemoryRebound(to: self, capacity: 1, { return 
                   $0.pointee })
        }).hashValue != 0) {
            i += 1
        }
        return i
}
oprogramowanie mats
źródło
0

Rozwiązałem ten problem dla siebie, tworząc protokół (EnumIntArray) i globalną funkcję narzędziową (enumIntArray), które bardzo łatwo dodają zmienną „All” do dowolnego wyliczenia (używając swift 1.2). Zmienna „all” będzie zawierać tablicę wszystkich elementów w wyliczeniu, dzięki czemu można użyć all.count do zliczenia

Działa tylko z wyliczeniami, które używają surowych wartości typu Int, ale być może może stanowić inspirację dla innych typów.

Zajmuje się także „luką w numeracji” i „nadmiernym czasem na iterację” problemów, które przeczytałem powyżej i gdzie indziej.

Chodzi o to, aby dodać protokół EnumIntArray do enum, a następnie zdefiniować zmienną statyczną „all”, wywołując funkcję enumIntArray i podając jej pierwszy element (i ostatni, jeśli w numeracji występują luki).

Ponieważ zmienna statyczna jest inicjalizowana tylko raz, narzut związany z przechodzeniem przez wszystkie wartości surowe uderza w twój program tylko raz.

przykład (bez przerw):

enum Animals:Int, EnumIntArray
{ 
  case Cat=1, Dog, Rabbit, Chicken, Cow
  static var all = enumIntArray(Animals.Cat)
}

przykład (z przerwami):

enum Animals:Int, EnumIntArray
{ 
  case Cat    = 1,  Dog, 
  case Rabbit = 10, Chicken, Cow
  static var all = enumIntArray(Animals.Cat, Animals.Cow)
}

Oto kod, który go implementuje:

protocol EnumIntArray
{
   init?(rawValue:Int)
   var rawValue:Int { get }
}

func enumIntArray<T:EnumIntArray>(firstValue:T, _ lastValue:T? = nil) -> [T]
{
   var result:[T] = []
   var rawValue   = firstValue.rawValue
   while true
   { 
     if let enumValue = T(rawValue:rawValue++) 
     { result.append(enumValue) }
     else if lastValue == nil                     
     { break }

     if lastValue != nil
     && rawValue  >  lastValue!.rawValue          
     { break }
   } 
   return result   
}
Alain T.
źródło
0

Lub możesz po prostu zdefiniować _countwyliczenie zewnętrzne i dołączyć je statycznie:

let _count: Int = {
    var max: Int = 0
    while let _ = EnumName(rawValue: max) { max += 1 }
    return max
}()

enum EnumName: Int {
    case val0 = 0
    case val1
    static let count = _count
}

W ten sposób, bez względu na to, ile utworzysz wyliczeń, zostanie ono utworzone tylko raz.

(jeśli statictak, usuń tę odpowiedź )

W
źródło
0

Poniższa metoda pochodzi z CoreKit i jest podobna do odpowiedzi sugerowanych przez innych. Działa to z Swift 4.

public protocol EnumCollection: Hashable {
    static func cases() -> AnySequence<Self>
    static var allValues: [Self] { get }
}

public extension EnumCollection {

    public static func cases() -> AnySequence<Self> {
        return AnySequence { () -> AnyIterator<Self> in
            var raw = 0
            return AnyIterator {
                let current: Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: self, capacity: 1) { $0.pointee } }
                guard current.hashValue == raw else {
                    return nil
                }
                raw += 1
                return current
            }
        }
    }

    public static var allValues: [Self] {
        return Array(self.cases())
    }
}

enum Weekdays: String, EnumCollection {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

Musisz po prostu zadzwonić Weekdays.allValues.count.

ThomasW
źródło
0
enum WeekDays : String , CaseIterable
{
  case monday = "Mon"
  case tuesday = "Tue"
  case wednesday = "Wed"
  case thursday = "Thu"
  case friday = "Fri"
  case saturday = "Sat"
  case sunday = "Sun"
}

var weekdays = WeekDays.AllCases()

print("\(weekdays.count)")
Nupur Sharma
źródło
-1
struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }
            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().enumCount
    }
}

enum E {
    case A
    case B
    case C
}

E.enumCases() // [A, B, C]
E.enumCount   //  3

ale zachowaj ostrożność podczas używania na typach innych niż wyliczanie. Niektóre obejście może być:

struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            guard sizeof(T) == 1 else {
                return nil
            }
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }

            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().count
    }
}

enum E {
    case A
    case B
    case C
}

Bool.enumCases()   // [false, true]
Bool.enumCount     // 2
String.enumCases() // []
String.enumCount   // 0
Int.enumCases()    // []
Int.enumCount      // 0
E.enumCases()      // [A, B, C]
E.enumCount        // 4
JMI
źródło
-1

Może używać stałej statycznej, która zawiera ostatnią wartość wyliczenia plus jeden.

enum Color : Int {
    case  Red, Orange, Yellow, Green, Cyan, Blue, Purple

    static let count: Int = Color.Purple.rawValue + 1

    func toUIColor() -> UIColor{
        switch self {
            case .Red:
                return UIColor.redColor()
            case .Orange:
                return UIColor.orangeColor()
            case .Yellow:
                return UIColor.yellowColor()
            case .Green:
                return UIColor.greenColor()
            case .Cyan:
                return UIColor.cyanColor()
            case .Blue:
                return UIColor.blueColor()
            case .Purple:
                return UIColor.redColor()
        }
    }
}
93sauu
źródło
-3

Jest to niewielkie, ale myślę, że lepszym rozwiązaniem O (1) byłoby ( TYLKO jeśli twoje wyliczenie Intzaczyna się od x itp.):

enum Test : Int {
    case ONE = 1
    case TWO
    case THREE
    case FOUR // if you later need to add additional enums add above COUNT so COUNT is always the last enum value 
    case COUNT

    static var count: Int { return Test.COUNT.rawValue } // note if your enum starts at 0, some other number, etc. you'll need to add on to the raw value the differential 
}

Aktualnie wybrana odpowiedź, którą nadal uważam, jest najlepszą odpowiedzią dla wszystkich wyliczeń, chyba że pracujesz, Intto polecam to rozwiązanie.

Drmorgan
źródło
3
Dodanie wartości do wyliczenia, która w rzeczywistości nie reprezentuje rodzaju wyliczenia, jest nieprzyjemnym zapachem kodu. Trudno mi nawet uzasadnić włączenie „WSZYSTKIEGO” lub „BRAK”, chociaż czasem może to być kuszące. Podanie „COUNT” tylko po to, by włamać się do tego problemu, jest bardzo śmierdzące.
Michael Peterson
1
Śmierdzący? Jeśli chcesz to tak nazwać. Performant? Tak. To programista decyduje o zaletach i wadach. Jest to w rzeczywistości ta sama odpowiedź na powyższą odpowiedź Zorayra, w której opisuje on bardziej szczegółowo, a nowa zaakceptowana odpowiedź jest również podobna. Ale dopóki szybki nie doda do tego interfejsu API; tego właśnie niektórzy z nas zdecydowali się użyć. Możesz dodać funkcję, która sprawdza wartość wyliczenia, która guardjest przeciw COUNTi generuje błąd, zwraca wartość false itp., Aby rozwiązać problem dotyczący reprezentacji typów.
Drmorgan