Overriding Enum init?(rawValue: String) to not be optional
The default initializer is failable
. It means that if the received parameter does not match a valid enum case it does return nil
.
Now you want to do 2 incompatibles things:
- You want to redefine the default initializer making it not failable. In fact you want a default enum value created when the received param is not valid.
- Inside your redefined initializer you want to call a failable initializer (which no longer exists) using the same name of the new one.
This is not possible, I the 3 possible solutions as follows:
- Creating a different init
You define a new not failable initializer with a default value, a different parameter name and inside it you call the default failable initializer.
enum Language: String { case english = "English", italian = "Italian", french = "French" init(fromRawValue: String) { self = Language(rawValue: fromRawValue) ?? .english }}
- Redefining the default init
You redefine the default initializer, you make it not failable and you write the full logic inside it.
enum Language: String { case english = "English", italian = "Italian", french = "French" init(rawValue: String) { switch rawValue { case "Italian": self = .italian case "French": self = .french default: self = .english } }}
- Creating a static func
enum Language: String { case english = "English", italian = "Italian", french = "French" static func build(rawValue: String) -> Language { return Language(rawValue: rawValue) ?? .english }}
Now you can build a Language
value writing:
let italian = Language.build(rawValue: "Italian") // Italianlet defaultValue = Language.build(rawValue: "Wrong input") // English
Adding to Luca's solution for redefining the default init, it is possible to additionally make the rawValue
parameter type optional, which cuts down on some code at the call site when the data source is not reliable.
enum PrecipitationType: String { case rain, snow, sleet, none typealias RawValue = String init(rawValue: String?) { guard let rawValue = rawValue else { self = .none; return } switch rawValue { case PrecipitationType.rain.rawValue: self = .rain case PrecipitationType.snow.rawValue: self = .snow case PrecipitationType.sleet.rawValue: self = .sleet default: self = .none } }}
When I initially tried this it generated multiple errors. The key was to redefine the RawValue
typealias to maintain conformance to RawRepresentable
.