Skip to content

Instantly share code, notes, and snippets.

@loganwright
Last active July 15, 2016 18:31
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganwright/c8a26b1faf538e40f747 to your computer and use it in GitHub Desktop.
Save loganwright/c8a26b1faf538e40f747 to your computer and use it in GitHub Desktop.
Int enum type extensions
protocol RawIntInitable {
init?(rawValue: Int)
}
extension RawIntInitable {
static var allCases: [Self] {
var caseIndex = 0
let generator = anyGenerator { Self(rawValue: caseIndex++) }
return Array(generator)
}
}

The point of this protocol is to be able to quickly and easily get all the cases of an enum as well as the number of cases quickly and easily. This makes things like modelling UITableView sections quick and easy.

Step 1: Conform your enum to RawIntInitable. All you have to do is add the protocol. If your enum derives from type Int, then you already conform. We just need to tell the compiler.

enum SettingsSections : Int, RawIntInitable {
    case Profile,
    Settings,
    FAQ,
    Feedback,
    LogOut
}

That's it, you can now use these functions wherever you might want.

ie:

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return SettingsSections.allCases.count
}

This allows us to count the sections without having an additional case devoted to the total number of cases that will need to be added to our switch statements.

Note

After a discussion with another dev about edge cases where an enum doesn't start at 0, or doesn't increment by 1, I created this more complex version:

protocol RawIntInitable {
    static var startingIndex: Int { get }
    static var incrementor: Int -> Int { get }

    init?(rawValue: Int)
}

extension RawIntInitable {
    
    static var startingIndex: Int {
        return 0
    }
    
    static var incrementor: Int -> Int {
        return { return $0 + 1 }
    }
    
    static var allCases: [Self] {
        var caseIndex = startingIndex
        let generator: AnyGenerator<Self> = anyGenerator {
            caseIndex = incrementor(caseIndex)
            return Self(rawValue: caseIndex)
        }
        return Array(generator)
    }
    
}

This way you can define a custom start, and a custom incrementation scheme for your enum if necessary.

@JessyCatterwaul
Copy link

Thanks! I think you ought to just make "allCases()" into "cases", though. numberOfCases is redundant when cases.count is so concise. Personally, I use the rule of, "if a function takes no parameters and returns something, it should be a property, not a function".

@loganwright
Copy link
Author

@jessy - Good suggestion, I prefer this as a variable this way. I'm going to keep the name allCases mostly for personal preference. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment