Skip to content

Instantly share code, notes, and snippets.

@designatednerd
Last active August 3, 2018 06:14
Show Gist options
  • Save designatednerd/390016f38c7f9559484c3bdcace066e1 to your computer and use it in GitHub Desktop.
Save designatednerd/390016f38c7f9559484c3bdcace066e1 to your computer and use it in GitHub Desktop.
Swift 3 Helpers for getting all the cases of a given enum [Swift 3]
import Foundation
/**
A swift protocol to make any Int enum able to count its cases.
Super-useful for making enums to help you deal with sections in tableviews without having to maintain a case for the count of the enum.
Originally developed by Logan Wright for Swift 2.0 here:
https://gist.github.com/LoganWright/c8a26b1faf538e40f747
Based on this and the subsequent 3 slides from my talk about
Laziness-Driven Development at CocoaConf Boston 2015:
https://speakerdeck.com/designatednerd/laziness-driven-development-in-ios-cocoaconf-boston-september-2015?slide=28
*/
public protocol CountableIntEnum {
/// - parameter rawValue: The raw Int value. Matches the initializer of RawRepresentable without the Self restrictions.
init?(rawValue: Int)
}
//MARK: Default Implementation
public extension CountableIntEnum {
/**
- returns: A generated array of all the cases in this enum. Mostly useful for calling with
.count so you can get the number of items in this enum.
*/
public static var AllCases: [Self] {
var caseIndex: Int = 0
let generator: AnyIterator<Self> = AnyIterator {
let _generator = Self(rawValue: caseIndex)
caseIndex += 1
return _generator
}
return Array(generator)
}
/**
Method to consolidate fatal erroring out if something ain't there.
- parameter index: The index (indexPath.row or indexPath.section, usually) of the thing you want to grab.
- returns: The retrieved enum case. Fatal errors if it can't find it.
*/
public static func forIndex(_ index: Int) -> Self {
guard let rowOrSection = Self(rawValue: index) else {
fatalError("Issue unwrapping row.")
}
return rowOrSection
}
}
import Foundation
public extension RawRepresentable {
/**
Method to consolidate fatal erroring if something that should definitely be in an enum which conforms
to `RawRepresentable` isn't there.
This means at the call site where you're trying to instantiate from a raw value instead of
```
guard let section = Sections(rawValue: sectionIndex) else { fatalError() }
switch section {...
```
You can just do
```
switch Sections.forValue(sectionIndex) {...
```
- parameter value: The raw value (indexPath.row or indexPath.section, usually) of the thing you want to grab.
- returns: The retrieved enum case. Fatal errors if it can't find it.
*/
static func forValue(_ value: RawValue) -> Self {
guard let type = Self.init(rawValue: value) else {
fatalError("Could not instantiate a \(Self.self) with value \(value)")
}
return type
}
}
import Foundation
/// A protocol to allow grabbing an array of all the cases of a string enum.
/// Inspired by: http://stackoverflow.com/a/32429125/681493
public protocol StringCaseListable {
/// - parameter rawValue: The raw string value. Matches the initializer of RawRepresentable without the Self restrictions.
init?(rawValue: String)
}
//MARK: - Default Implementation
public extension StringCaseListable {
/// - returns: A generated array of all the cases in this enum.
static var AllCases: [Self] {
var caseIndex: Int = 0
// Create an iterator
let generator: AnyIterator<Self> = AnyIterator {
// In which each time it goes around, the case index is used
let current: Self = withUnsafePointer(to: &caseIndex) {
// To grab the appropriate memory for one of this type, and grab it's pointee
$0.withMemoryRebound(to: Self.self, capacity: 1) { $0.pointee }
}
caseIndex += 1
return current
}
return Array(generator)
}
}
@alexiscn
Copy link

alexiscn commented Aug 3, 2018

when enum implement CodingKey

enum Food: String, CodingKey, StringCaseListable {
    case apple = "Apple"
    case banana = "b"
}

for key in Food.AllCases {
    print(key)
}
 // prints Food(stringValue: "Apple", intValue: nil)
 // prints Food(stringValue: "b", intValue: nil)

But I excepted prints apple and banana.

It seems CodingKey breaks down the description of Food and can not get original key anymore. Any suggestion ?

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