Get all cases of an enum in Swift 4.2 with CaseIterable - Thomas Bibby

Swift 4.2 brings a really handy protocol for Swift enums that Dave Sims and I discussed back when he gave his talk on Swift enums to the iOS developer meetup in Limerick (and subsequently in Dublin and Indianapolis). The problem is this: when you have an enum in Swift you often want an array with all its cases. Because you’re displaying those cases in a table view or a segmented control or any other UI element that has a concept of an index. I’ve settled on the code like the following to manually add the relevant array:

public protocol AllCaseable {
    static var allCases:  [Self] { get }
}

enum PaymentType: AllCaseable {
    case cash
    case creditCard
    case voucher
    static var allCases: [PaymentType] {
        return [.cash, .creditCard, .voucher]
    }
}

This works OK but it’s ultimately manual and error prone. Add a new customerAccount case? Well if you forget to add it to your allCases() function the compiler won’t complain at you. And it’s another protocol conformance that you have to write manually that you feel really should be built in.

Swift 4.2 changes that with the CaseIterable protocol. Now you can just write:


enum PaymentType: CaseIterable {
    case cash
    case creditCard
    case voucher
}

And you get the allCases property for free. Add a new enum case and you don’t have to write any other extra code to get your table views and your segmented controls to update. Surprisingly Swift 4.2 didn’t ship with Xcode 9.4 yesterday (which makes me think we mightn’t get Swift 5 with Xcode 10, which would be the right choice I think, ABI stability is too important to try and shoehorn into Apple’s annual release cycle) so you can only try it out with development builds of Swift, but it’s going to be pretty great when it ships. Note that it doesn’t work out of the box with enums that have associated values however.

Side note: I’m happy I the allCases property I’ve been using was chosen for the CaseIterable protocol, but I have to admit “CaseIterable” is way better than my “AllCaseable”. I’m a bit rubbish at picking names for Swift protocols.