Default value for Enum in Swift
Another approach that works in Swift 3 (maybe 2, don't know):
enum PersonType: String { case cool = "cool" case nice = "nice" case soLazy = "so-lazy" case other}let person = PersonType(rawValue: "funny") ?? .other
The person variable is of type PersonType.other in this case.
The downside to this is that you don't know the raw string value of the .other case.
Drop the raw type, and use enum
with associated value:
public enum PersonType { case Cool case Nice case SoLazy case Unknown(String) static func parse(s:String) -> PersonType { switch s { case "Cool" : return .Cool case "Nice" : return .Nice case "SoLazy" : return .SoLazy default: return Unknown(s) } }}
The downside to dropping the raw type is that you must provide some logic for parsing the known enum
values. The upside, however, is that you can fit anything else into a single Unknown
case, while keeping the actual "unknown" value available for later use.
This goes pretty close but I would like to be able to store the value that can be associated with it, kind of like you can with C.
enum Errors: Int { case transactionNotFound = 500 case timeout = -1001 case invalidState = 409 case notFound = 404 case unknown init(value: Int) { if let error = Errors(rawValue: value) { self = error } else { self = .unknown } }}Errors(value: 40) // .unknownErrors(value: 409) // .invalidStateErrors(value: 500) // .transactionNotFound
Had to create a custom initializer, otherwise it is recursive. And it is still possible to create using the rawValue initializer by accident.
This however feels more Swifty, I removed the : Int
type specifier which allows you to use associated values, now the exceptional case that we don't do anything special is handled in the other
:
enum Errors2 { case transactionNotFound case timeout case invalidState case notFound case other(Int) init(rawValue: Int) { switch rawValue { case 500: self = .transactionNotFound case -1001: self = .timeout case 409: self = .invalidState case 404: self = .notFound default: self = .other(rawValue) } }}Errors2(rawValue: 40) // .other(40)Errors2(rawValue: 409) // .invalidStateErrors2(rawValue: 500) // .transactionNotFoundErrors2(rawValue: -1001) // .timeout
With this I could get the actual value for an "other" error, and I can use the rawValue so it acts a lot like an Int based enum. There is the single case statement to map the names but from then on you can use the names and never need to refer to the numbers.