如何实现Swift中类似Java Enum.valueOf的字符串转枚举值功能
根据字符串获取Int类型rawValue的枚举实例
需求明确:枚举rawValue用Int(方便持久化),每个枚举值对应专属字符串(用于UI本地化),需要实现从字符串反向查找枚举实例的方法。下面提供两种实用方案:
方案一:自定义字符串属性 + CaseIterable遍历(推荐)
这种方案把枚举的展示字符串和case解耦,适合本地化场景,即使修改case名称也不影响UI展示的字符串。
enum Unit: Int { case SECOND = 0 case MINUTE = 1 case HOUR = 2 // 这里存本地化字符串的key,后续UI展示时用NSLocalizedString获取对应语言文本 var displayKey: String { switch self { case .SECOND: return "unit_second" case .MINUTE: return "unit_minute" case .HOUR: return "unit_hour" } } // 根据输入的字符串查找对应枚举,返回可选型避免无效输入崩溃 static func valueOf(unit: String) -> Unit? { return allCases.first { $0.displayKey == unit } } } // 让枚举实现CaseIterable协议,才能使用allCases遍历所有case extension Unit: CaseIterable {}
使用示例
// 假设从本地化配置或用户选择中拿到字符串 let selectedKey = "unit_minute" if let unit = Unit.valueOf(unit: selectedKey) { print(unit.rawValue) // 输出1,可用于持久化 print(unit.displayKey) // 输出unit_minute,用于获取本地化文本 }
方案二:匹配枚举Case名称(仅当字符串是case名时适用)
如果你的输入字符串就是枚举的case名称(比如"SECOND"),可以通过Mirror反射遍历所有case来匹配:
enum Unit: Int { case SECOND case MINUTE case HOUR static func valueOf(unit: String) -> Unit? { let mirror = Mirror(reflecting: self) for case let (label?, value) in mirror.children { if label == unit, let matchedUnit = value as? Unit { return matchedUnit } } return nil } }
注意
这种方案依赖case名称,一旦修改case名,对应的输入字符串也必须同步修改,灵活性较差,不推荐用于本地化场景。
额外建议
- 优先返回
Unit?可选类型:如果输入的字符串没有对应枚举,返回nil比强行返回默认值更安全,能提前发现无效输入的问题。 - 持久化时直接存储枚举的
rawValue(Int类型):相比字符串,Int存储更高效,也避免了字符串变更导致的持久化数据失效问题。 - 本地化展示时通过枚举的
displayKey获取对应语言的文本:比如NSLocalizedString(unit.displayKey, comment: "")。
内容的提问来源于stack exchange,提问作者berger-devel
相关产品推荐
相关产品推荐

