How to get enum from raw value in Swift?
Solution 1
Too complicated, just assign the raw values directly to the cases
enum TestEnum: String {
case Name = "Name"
case Gender = "Gender"
case Birth = "Birth Day"
}
let name = TestEnum(rawValue: "Name")! //Name
let gender = TestEnum(rawValue: "Gender")! //Gender
let birth = TestEnum(rawValue: "Birth Day")! //Birth
If the case name matches the raw value you can even omit it
enum TestEnum: String {
case Name, Gender, Birth = "Birth Day"
}
In Swift 3+ all enum cases are lowercased
Solution 2
Full working example:
enum TestEnum: String {
case name = "A Name"
case otherName
case test = "Test"
}
let first: TestEnum? = TestEnum(rawValue: "A Name")
let second: TestEnum? = TestEnum(rawValue: "OtherName")
let third: TestEnum? = TestEnum(rawValue: "Test")
print("\(first), \(second), \(third)")
All of those will work, but when initializing using a raw value it will be an optional. If this is a problem you could create an initializer or constructor for the enum to try and handle this, adding a none
case and returning it if the enum couldn't be created. Something like this:
static func create(rawValue:String) -> TestEnum {
if let testVal = TestEnum(rawValue: rawValue) {
return testVal
}
else{
return .none
}
}
Solution 3
With Swift 4.2 and CaseIterable protocol it is not that hard at all!
Here is an example of how to implement it.
import UIKit
private enum DataType: String, CaseIterable {
case someDataOne = "an_awesome_string_one"
case someDataTwo = "an_awesome_string_two"
case someDataThree = "an_awesome_string_three"
case someDataFour = "an_awesome_string_four"
func localizedString() -> String {
// Internal operation
// I have a String extension which returns its localized version
return self.rawValue.localized
}
static func fromLocalizedString(localizedString: String) -> DataType? {
for type in DataType.allCases {
if type.localizedString() == localizedString {
return type
}
}
return nil
}
}
// USAGE EXAMPLE
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let dataType = DataType.fromLocalizedString(localizedString: self.title) {
loadUserData(type: dataType)
}
}
You can easily modify it to return the DataType based on the rawValue. I hope it helps!
Solution 4
You can define enum like this -
enum TestEnum: String {
case Name, Gender, Birth
}
OR
enum TestEnum: String {
case Name
case Gender
case Birth
}
you can provide an init method which defaults to one of the member values.
enum TestEnum: String {
case Name, Gender, Birth
init() {
self = .Gender
}
}
In the example above, TestEnum.Name has an implicit raw value of "Name", and so on.
You access the raw value of an enumeration case with its rawValue property:
let testEnum = TestEnum.Name.rawValue
// testEnum is "Name"
let testEnum1 = TestEnum()
// testEnum1 is "Gender"
Solution 5
Display the rawvalue using Enum
import UIKit
enum car: String {
case bmw = "BMW"
case jaquar = "JAQUAR"
case rd = "RD"
case benz = "BENZ"
}
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
label.text = car.bmw.rawValue
}
}
Leo
Updated on December 04, 2021Comments
-
Leo over 2 years
I'm trying to get enum type from raw value:
enum TestEnum: String { case Name case Gender case Birth var rawValue: String { switch self { case .Name: return "Name" case .Gender: return "Gender" case .Birth: return "Birth Day" } } } let name = TestEnum(rawValue: "Name") //Name let gender = TestEnum(rawValue: "Gender") //Gender
But it seems that
rawValue
doesn't work for string with spaces:let birth = TestEnum(rawValue: "Birth Day") //nil
Any suggestions how to get it?
-
matt about 8 yearsExcept that the variables
name
and so on are now Optionals, which is not likely to be what the OP wants. -
Marcus Rossel about 8 yearsThere is no other way, than receiving back an optional (unless you want a crash, when a string is passed, that does not correspond to an enum case).
-
vadian about 8 years@matt - right, but since you know the case names at compile time you can safely unwrap the optionals. I edited the answer.
-
matt about 8 yearsExcellent. I think the OP will find that more useful!
-
keshav vishwkarma about 8 years@matt super, compile time checking is more powerful to prevent the runtime crashes
-
Hugo over 7 yearsForce unwrapping an enum created from it's RawValue can cause runtime exceptions. It would be better to use the "if let" construction to unwrap the value. Also see: Apple Enum Raw Value documentation
-
vadian over 7 years@Hugo You are right if the raw value is a user defined variable. On the other hand the number of enum cases cannot be changed at runtime and the developer (you) knows the values. So if the raw value to initialize the enum is a literal string the runtime error reveals a design error.
-
bbjay about 6 years
init(_ str: String) { self = TestEnum(rawValue: str) ?? .none }
as an additional init does the same -
GetSwifty about 6 yearsThat's another option. Personally I prefer to avoid inits with the same Typed params if possible.
-
Leo about 5 yearsI believe there is something wrong with the design if it's required to restore an enum case from a localized string.
-
BelfDev about 5 years@Leo, it's totally OK to discuss whether the retrieval of enum case from a localized string is ideal or not. In fact, I personally agree with you that it is not -- but sometimes we work in huge projects where we cannot simply go ahead and change anything we want. That said, I think you will agree with me when I say that this kind of discussion is out of scope... The whole point is that you can retrieve enum cases from any given associated type. It answers your initial question from 2016. Cheers!
-
Mattie over 2 yearsThe most helpful answers are usually code and an explanation of how/why the code is used. You aren't wrong here, but a little more effort would help make this a high quality answer.