I found two answered questions about how to get an enum constant's name as a String. I want to do the vice-versa, i.e. getting the enum constant with a given name in a String:
enum Unit: Int {
case SECOND
case MINUTE
case HOUR
static func valueOf(unit: String) -> Unit {
// ?
}
}
I want to keep the rawValue
to be an Int
.
Update: To make the intention clear, I want to persist an object that has a Unit
property. I also want to display the unit chosen by the user in the UI, as a localized string. Therefore I need to assign a constant and unique value, the integer, and a String to each enum value.
CodePudding user response:
There is no easy built-in conversion. You can make the enum iterable and iterate over the strings util you find the correct one:
enum Unit: Int, CaseIterable {
case SECOND
case MINUTE
case HOUR
static func valueOf(unit: String) -> Unit? {
for x in Unit.allCases {
if String(describing: x)==unit {
return x
}
}
return nil
}
}
You'd need to deal the the possibility that an input string might not mach any valid case-string. I used an optional, but you could as well throw an exception.
Several remarks:
- This code is case sensitive. So
"HOUR"
will not lead to the same result as"hour"
. If needed, add a case normalisation. - This code is not optimal, since it will perform a lot of string conversions every iteration on every call. A better alternative would be to initialise a dictionary once, and use it subsequently
The latter could look like:
private static var ready = false
private static var strings = [String : Unit] ()
static func valueOf2(unit: String) -> Unit? {
if !ready {
for x in Unit.allCases {
strings [String(describing: x)]=x
}
ready = true
}
return strings[unit]
}
CodePudding user response:
Swift has a CaseIterable
protocol that you can use to find the case from its raw value.
enum Unit: Int, CaseIterable {
case second = 100
case minute = 200
case hour = 300
static func caseFrom(rawValue: Int) -> Unit? {
return allCases.first { $0.rawValue == rawValue }
}
}
if let unitCase = Unit.caseFrom(rawValue: 200) {
print(unitCase)
}
The premise of this enum is a bit confusing to me but this is what you're looking for.