222

How can I determine the number of cases in a Swift enum?

(I would like to avoid manually enumerating through all the values, or using the old "enum_count trick" if possible.)

Community
  • 1
  • 1
Robert Atkins
  • 23,528
  • 15
  • 68
  • 97

26 Answers26

245

As of Swift 4.2 (Xcode 10) you can declare conformance to the CaseIterable protocol, this works for all enumerations without associated values:

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

The number of cases is now simply obtained with

print(Stuff.allCases.count) // 4

For more information, see

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    In latest version of swift, its throwing error "Type 'DAFFlow' does not conform to protocol 'RawRepresentable'". Why is it forcing for me to follow that? Any idea? – Satyam May 17 '18 at 07:01
  • @Satyam: What is DAFFlow? – Martin R May 17 '18 at 07:05
  • sorry I forgot to mention that "DAFFlow' is a simple enum that don't inherit from any other protocol. – Satyam May 17 '18 at 07:13
  • sorry I'm trying it in Swift 4.1 version. I think it may not work. – Satyam May 17 '18 at 07:14
  • @Satyam: This requires a recent version of Swift 4.2. – Martin R May 17 '18 at 07:16
  • 1
    This is the best solution, but just for clarity - Apple developers will only really be able to start using this once Xcode 10 (and hence Swift 4.2) come out of beta (so likely around 14th September 2018). – JosephH Sep 05 '18 at 14:26
  • Not working. Note that I'm trying it on a enum with a raw type, so: `enum Stuff: String, CaseIterable`. I get: `Instance member 'count' cannot be used on type 'ViewController.myEnum.AllCases' (aka 'Array')` –  Nov 27 '18 at 18:28
  • OK so... `AllCases` does not work, but `allCases` does. Hu. –  Nov 27 '18 at 18:33
  • @DaniSpringer: `allCases` is the method, it must be called on the type, i.e. `Stuff.allCases`. `AllCases` is the *type* of `allCases`, usually an array. – Martin R Nov 27 '18 at 18:35
  • Ah, so AllCases it to see what type the array contains? –  Nov 27 '18 at 18:45
  • 1
    @DaniSpringer: You'll find the gory details at https://github.com/apple/swift-evolution/blob/master/proposals/0194-derived-collection-of-enum-cases.md#detailed-design. But usually you don't need that type explicitly, due to the automatic type inference of the compiler. – Martin R Nov 27 '18 at 18:56
  • @martinR I am pretty sure it also works with Swift 4.0 - the documentation says it's an Xcode 10 thing rather than a language version. I know, sounds strange... – Antonio Jan 18 '19 at 17:19
  • @Antonio: Xcode 10 comes with Swift 4.2 only – what you select in the build settings is the “language compatibility version.” Many new language features are available regardless of the chosen compatibility version. – Martin R Jan 18 '19 at 17:45
  • @MartinR that's the case then. I upgraded a project to Swift 4.2 a couple weeks ago, but I used `CaseIterable` before that, and it worked. – Antonio Jan 18 '19 at 21:08
  • @Antonio: Then I do not know. – Martin R Jan 18 '19 at 21:20
  • @MartinR Can Objective-C callers "see" enumerations with Int raw types if the enum conforms to `CaseIterable`? – Adrian May 06 '20 at 03:18
147

I have a blog post that goes into more detail on this, but as long as your enum's raw type is an integer, you can add a count this way:

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
    }()
}
James Kuang
  • 10,710
  • 4
  • 28
  • 38
Nate Cook
  • 92,417
  • 32
  • 217
  • 178
  • 19
    While nice because you don't need to hardcode a value, this will instantiate every enum value each time it is called. That is O(n) instead of O(1). :( – Code Commander Mar 05 '15 at 17:55
  • 4
    This is a good solution for contiguous Int. I prefer a slight modification. Turn the static count property into a static method countCases() and assign it to a static constant caseCount which is lazy and improves performance with repeated calls. – Tom Pelaia Jul 15 '15 at 14:30
  • @TomPelaia can you show an example? with the above being O(n) is your approach better – Shams Ahmed Oct 20 '15 at 11:32
  • 2
    @ShamsAhmed: Converted the computed var into a static one. – Nate Cook Oct 20 '15 at 14:31
  • I posted the code based on this approach and using a reusable protocol called CaseCountable. – Tom Pelaia Oct 20 '15 at 15:53
  • Nice solution for named Table|CollectionView sections. – kelin Apr 02 '17 at 13:02
  • 4
    What if you miss some value in the enum? e.g. `case A=1, B=3` ? – Sasho Aug 03 '17 at 08:27
  • 2
    There are 2 assumptions besides the `enum` having an `Int` raw value that you forgot to mention: Swift enum's with Int raw values do not have to start from 0 (even though that's the default behaviour) and their raw values can be arbitrary, they don't have to increment by 1 (even though that's the default behaviour). – Dávid Pásztor May 04 '18 at 14:36
98

Xcode 10 update

Adopt the CaseIterable protocol in the enum, it provides a static allCases property which contains all enum cases as a Collection . Just use of its count property to know how many cases the enum has.

See Martin's answer for an example (and upvote his answers rather than mine)


Warning: the method below doesn't seem to work anymore.

I'm not aware of any generic method to count the number of enum cases. I've noticed however that the hashValue property of the enum cases is incremental, starting from zero, and with the order determined by the order in which the cases are declared. So, the hash of the last enum plus one corresponds to the number of cases.

For example with this enum:

enum Test {
    case ONE
    case TWO
    case THREE
    case FOUR

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

count returns 4.

I cannot say if that's a rule or if it will ever change in the future, so use at your own risk :)

Antonio
  • 71,651
  • 11
  • 148
  • 165
  • 51
    Live by the undocumented feature, die by the undocumented feature. I like it! – Nate Cook Nov 23 '14 at 22:25
  • 9
    We shouldn't really be relying on `hashValues` for these things; all we know is that it's some random unique value - could change very easily in the future depending on some compiler implementation detail; but overall, the lack of built-in counting functionality is disturbing. – Zorayr Apr 26 '15 at 01:09
  • 17
    If you don't mind explicitly setting `case ONE = 0`, you can then replace `hashValue` with `rawValue`. – Kevin Qi Aug 12 '15 at 14:22
  • @KevinQi: that's pretty much what's done in NateCook's answer – Antonio Aug 12 '15 at 14:24
  • 3
    the concern here is the use of an undocumented property of hashValue, so my suggestion is to use a documented property of rawValue. – Kevin Qi Aug 12 '15 at 14:30
  • @KevinQi Yeah I know - in fact that's clearly stated in the answer :) – Antonio Aug 12 '15 at 14:31
  • 7
    You've already hardcoded the fact of which constant is the highest value, Better and safer to just use something like `static var count = 4` rather than leaving your destiny in the fate of future implementations of Swift – Dale Aug 20 '16 at 06:41
  • This is a neat hack, but unfortunately, as with rawValue, hashValue is not supported by enums which use associated values. – ff10 Feb 17 '17 at 16:31
  • This should not be the accepted answer, as it is undocumented and can change at any time. – KoCMoHaBTa Jun 23 '17 at 11:54
  • Can cause future bugs: In case of developer add a new enum type he needs to remember to change the count – evya Mar 19 '18 at 11:28
  • This now returns 4791270226569771584... No longer works under xCode 10.1 – Don Miguel Jan 18 '19 at 13:47
  • 1
    @DonMiguel maybe now that's a real hash value :-) I've updated the answer, thanks for letting me know – Antonio Jan 18 '19 at 17:23
72

I define a reusable protocol which automatically performs the case count based on the approach posted by 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
    }
}

Then I can reuse this protocol for example as follows:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)
sig
  • 6,024
  • 2
  • 26
  • 31
Tom Pelaia
  • 1,275
  • 10
  • 9
38

Create static allValues array as shown in this answer

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

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

...

let count = ProductCategory.allValues.count

This is also helpful when you want to enumerate the values, and works for all Enum types

Community
  • 1
  • 1
david72
  • 7,151
  • 3
  • 37
  • 59
  • Although not as elegant as the extensions solution and very manual, I believe this is the most useful as it offers a lot more than count. It gives you order of values and a list of all the values. – Nader Eloshaiker Dec 10 '17 at 01:36
  • 2
    You could also add the count to the enum by doing `static let count = allValues.count`. Then you could make the `allValues` private if desired. – ThomasW Mar 20 '18 at 02:29
15

If the implementation doesn't have anything against using integer enums, you could add an extra member value called Count to represent the number of members in the enum - see example below:

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

Now you can get the number of members in the enum by calling, TableViewSections.Count.rawValue which will return 2 for the example above.

When you're handling the enum in a switch statement, make sure to throw an assertion failure when encountering the Count member where you don't expect it:

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
  • 23,770
  • 8
  • 136
  • 129
  • I like that solution as it changes the count automatically when adding more enum values. However keep in mind that this only works when the rawValues of the enum start with 0. – joern Jun 25 '15 at 07:42
  • 2
    Agree, there are two restrictions: must be an integer enum and must start at zero and continue incrementally. – Zorayr Jun 25 '15 at 17:37
  • 3
    I thought the entire point of Swift's more powerful enums was that we wouldn't have to use the same hacks we used in Objective-C :/ – pkamb Apr 14 '16 at 19:55
14

This kind of function is able to return the count of your enum.

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
  • 31,918
  • 20
  • 95
  • 134
  • 3
    This no longer works for Swift 3. Trying to work out the proper implementation, but coming up empty – Cody Winton Sep 26 '16 at 17:33
  • This will be very unfun to debug if the memory address immediately adjacent to the end of the `enum` is *also* `Hashable` of the same type. – NRitH Nov 15 '17 at 23:49
10

Oh hey everybody, what about unit tests?

func testEnumCountIsEqualToNumberOfItemsInEnum() {

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

    XCTAssert(max == Test.count)
}

This combined with Antonio's solution:

enum Test {

    case one
    case two
    case three
    case four

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

in the main code gives you O(1) plus you get a failing test if someone adds an enum case five and doesn't update the implementation of count.

buildsucceeded
  • 4,203
  • 4
  • 34
  • 72
10

String Enum with Index

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)!
    }
}

count : eEventTabType.allValues.count

index : objeEventTabType.index

Enjoy :)

kalpesh jetani
  • 1,775
  • 19
  • 33
7

This function relies on 2 undocumented current(Swift 1.1) enum behavior:

  • Memory layout of enum is just a index of case. If case count is from 2 to 256, it's UInt8.
  • If the enum was bit-casted from invalid case index, its hashValue is 0

So use at your own risk :)

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")
    }
}

Usage:

enum Foo:String {
    case C000 = "foo"
    case C001 = "bar"
    case C002 = "baz"
}
enumCaseCount(Foo) // -> 3
rintaro
  • 51,423
  • 14
  • 131
  • 139
5

I wrote a simple extension which gives all enums where raw value is integer a count property:

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())
    }
}

Unfortunately it gives the count property to OptionSetType where it won't work properly, so here is another version which requires explicit conformance to CaseCountable protocol for any enum which cases you want to count:

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())
    }
}

It's very similar to the approach posted by Tom Pelaia, but works with all integer types.

bzz
  • 5,556
  • 24
  • 26
5
enum EnumNameType: Int {
    case first
    case second
    case third

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

print(EnumNameType.count) //3

OR

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

print(EnumNameType.count.rawValue) //3

*On Swift 4.2 (Xcode 10) can use:

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

print(EnumNameType.allCases.count) //3
Lê Cường
  • 391
  • 4
  • 4
4

Of course, it's not dynamic but for many uses you can get by with a static var added to your Enum

static var count: Int{ return 7 }

and then use it as EnumName.count

Ian Dundas
  • 553
  • 1
  • 6
  • 17
2

For my use case, in a codebase where multiple people could be adding keys to an enum, and these cases should all be available in the allKeys property, it's important that allKeys be validated against the keys in the enum. This is to avoid someone forgetting to add their key to the all keys list. Matching the count of the allKeys array(first created as a set to avoid dupes) against the number of keys in the enum ensures that they are all present.

Some of the answers above show the way to achieve this in Swift 2 but none work in Swift 3. Here is the Swift 3 formatted version:

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)
}

Depending on your use case, you might want to just run the test in development to avoid the overhead of using allKeys on each request

Chris Mitchelmore
  • 5,976
  • 3
  • 25
  • 33
2

Why do you make it all so complex? The SIMPLEST counter of Int enum is to add:

case Count

In the end. And... viola - now you have the count - fast and simple

Dimitar Marinov
  • 922
  • 6
  • 14
  • 2
    This a) adds an extraneous enum case and b) won't work if the enum's raw type is anything other than Int. – Robert Atkins May 03 '17 at 16:28
  • This actually isn't a bad answer. Like @Tom Pelaia's answer above, however, it requires the raw values to start at `0` and have no gaps in the sequence. – NRitH Nov 15 '17 at 23:46
2
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)")
Nathan
  • 13
  • 1
  • 4
Nupur Sharma
  • 1,106
  • 13
  • 15
1

If you don't want to base your code in the last enum you can create this function inside your enum.

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
}
1

A Swift 3 version working with Int type enums:

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
    }
}

Credits: Based on the answers by bzz and Nate Cook.

Generic IntegerType (in Swift 3 renamed to Integer) is not supported, as it's a heavily fragmented generic type which lacks a lot of functions. successor is not available with Swift 3 anymore.

Be aware that the comment from Code Commander to Nate Cooks answer is still valid:

While nice because you don't need to hardcode a value, this will instantiate every enum value each time it is called. That is O(n) instead of O(1).

As far as I know there is currently no workaround when using this as protocol extension (and not implementing in each enum like Nate Cook did) due to static stored properties not being supported in generic types.

Anyway, for small enums this should be no issue. A typical use case would be the section.count for UITableViews as already mentioned by Zorayr.

Frederik Winkelsdorf
  • 4,383
  • 1
  • 34
  • 42
1

Extending Matthieu Riegler answer, this is a solution for Swift 3 that doesn't require the use of generics, and can be easily called using the enum type with 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
}
matsoftware
  • 766
  • 6
  • 12
0

I solved this problem for myself by creating a protocol (EnumIntArray) and a global utility function (enumIntArray) that make it very easy to add an "All" variable to any enum (using swift 1.2). The "all" variable will contain an array of all elements in the enum so you can use all.count for the count

It only works with enums that use raw values of type Int but perhaps it can provide some inspiration for other types.

It also addresses the "gap in numbering" and "excessive time to iterate" issues I've read above and elsewhere.

The idea is to add the EnumIntArray protocol to your enum and then define an "all" static variable by calling the enumIntArray function and provide it with the first element (and the last if there are gaps in the numbering).

Because the static variable is only initialized once, the overhead of going through all raw values only hits your program once.

example (without gaps) :

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

example (with gaps) :

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

Here's the code that implements it:

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.
  • 40,517
  • 4
  • 31
  • 51
0

Or you can just define the _count outside the enum, and attach it statically:

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
}

That way no matter how many enums you create, it'll only ever be created once.

(delete this answer if static does that)

A T
  • 13,008
  • 21
  • 97
  • 158
0

The following method comes from CoreKit and is similar to the answers some others have suggested. This works with 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
}

Then you just need to just call Weekdays.allValues.count.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
0

Just want to share a solution when you have an enum with associated values.

enum SomeEnum {
  case one
  case two(String)
  case three(String, Int)
}
  • CaseIterable doesn't provide allCases automatically.
  • We can't provide a raw type like Int for your enum to calculate cases count somehow.

What we can do is to use power of switch and fallthrough keyword.

extension SomeEnum {
  static var casesCount: Int {
    var sum = 0

    switch Self.one { // Potential problem
       case one:
         sum += 1
         fallthrough

       case two:
         sum += 1
         fallthrough

       case three:
         sum += 1
    }

    return sum
  }
}

So now you can say SomeEnum.casesCount.

Remarks:

  • We still have a problem with switch Self.one {..., we hardcoded the first case. You can easily hack this solution. But I used it just for unit tests so that was not a problem.
  • If you often need to get cases count in enums with associated values, think about code generation.
-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

but be careful with usage on non-enum types. Some workaround could be:

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
  • 2,530
  • 15
  • 26
-1

It can use a static constant which contains the last value of the enumeration plus one.

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
  • 3,770
  • 3
  • 27
  • 43
-4

This is minor, but I think a better O(1) solution would be the following (ONLY if your enum is Int starting at x, etc.):

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 
}

The current selected answer I still believe is the best answer for all enums, unless you are working with Int then I recommend this solution.

Drmorgan
  • 529
  • 4
  • 10
  • 3
    Adding a value to your enum that doesn't actually represent the type of the enum is a bad code smell. I find it hard to even justify including an "ALL", or "NONE" even though it can be tempting sometimes. Including a "COUNT" just to hack around this issue is very stinky. – Michael Peterson May 06 '16 at 04:05
  • 1
    Stinky? If you want to call it that sure. Performant? Yes. It is up to the developer to decide the pros and cons. This is actually the same answer to Zorayr's answer above where he goes into more detail about it, and the new accepted answer is also similar. But until swift adds an api for it; this is what some of us have decided to use. You can add a function that validates the enum value that `guard`s against `COUNT` and throws an error, returns false, etc. to resolve your concern of representation of types. – Drmorgan May 06 '16 at 13:36