我有enum
:
public enum PersonType:String {
case Cool = "cool"
case Nice = "rude"
case SoLazy = "so-lazy"
public var description: String {
switch self {
case .Cool:
return "Cool person"
case .Nice:
return "Nice person"
case .SoLazy:
return "its so lazy person"
}
}
public var typeImage: String {
switch self {
case .Cool:
return "cool.png"
case .Nice:
return "img_nice.png"
case .Solazy:
return "lazy.png"
}
}
}
问题我不知道所有人的类型键,所以我需要处理类型为人的默认情况,并给它描述将是它的关键像" so-lazy& #34;和默认图像。
让我说我从网络服务获得此结果:
[
{
name: "john",
key: "cool"
},
{
name: "paul",
key: "funny"
}
]
我需要一个默认案例来处理密钥"搞笑"
这是我在解析和创建person对象时如何初始化我的枚举:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
}
我想要一个else
或更好的方法来处理枚举中未知密钥的情况,并为它们提供密钥作为描述和默认图像。
答案 0 :(得分:16)
另一种适用于Swift 3的方法(可能是2,不知道):
enum PersonType: String {
case cool = "cool"
case nice = "nice"
case soLazy = "so-lazy"
case other
}
let person = PersonType(rawValue: "funny") ?? .other
在这种情况下,person变量的类型为PersonType.other。
这样做的缺点是你不知道.other案例的原始字符串值。
答案 1 :(得分:13)
删除原始类型,并使用enum
及其相关值:
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)
}
}
}
删除原始类型的缺点是您必须提供一些逻辑来解析已知的enum
值。然而,好处是,您可以将任何其他内容放入单个Unknown
案例中,同时保持实际的“未知”值可供以后使用。
答案 2 :(得分:5)
这非常接近,但我希望能够存储与之相关的价值,就像你可以用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) // .unknown
Errors(value: 409) // .invalidState
Errors(value: 500) // .transactionNotFound
必须创建自定义初始化程序,否则它是递归的。并且仍然可以偶然地使用rawValue初始化器创建。
然而,这感觉更加Swifty,我删除了允许您使用关联值的: Int
类型说明符,现在我们不执行任何特殊操作的例外情况在other
中处理:< / p>
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) // .invalidState
Errors2(rawValue: 500) // .transactionNotFound
Errors2(rawValue: -1001) // .timeout
有了这个,我可以得到“其他”错误的实际值,我可以使用rawValue,因此它的行为很像基于Int的枚举。有一个单一案例声明来映射名称,但从那时起,您可以使用名称,永远不需要参考数字。
答案 3 :(得分:2)
这个问题现在已经很老了,在Swift世界中已经发生了很多变化。对于Swift 5,我建议使用以下方法,该方法包括为枚举创建一个新的初始化程序:
public enum PersonType:String, ExpressibleByNilLiteral {
case Cool = "cool"
case Nice = "rude"
case SoLazy = "so-lazy"
public init(nilLiteral:()) {
self = .SoLazy
}
public init!(_ optionalValue:RawValue?) {
guard let rawValue = optionalValue,
let validValue = PersonType(rawValue:rawValue) else {
self = .SoLazy
return
}
self = validValue
}
public var description: String {
switch self {
case .Cool return "Cool Person"
//... etc
}
}
public var typeImage: String {
switch self {
case .Cool return "cool.png"
//... etc
}
}
}
像这样使用它:
self.personType = PersonType(personTypeKey)
或者像这样:
self.personType = nil
无论哪种情况,即使该值对于PersonType
枚举无效或只是nil,您都将获得一个有效的枚举,该枚举设置为默认值.SoLazy
这与该线程中的其他几种方法类似,但是它使用多个guard let =
语句来保证其有效,而不是列出所有可能的有效值(如果有很多的话可能很麻烦)。
答案 4 :(得分:1)
尝试这种方法。
public enum PersonType:String {
case Cool = "cool"
case Nice = "rude"
case SoLazy = "so-lazy"
static let allKeys = [Cool.rawValue, Nice.rawValue, SoLazy.rawValue]
}
extension PersonType
{
func description(personTypeKey : String) -> String {
if PersonType.allKeys.contains(personTypeKey)
{
switch self {
case .Cool:
return "Cool person"
case .Nice:
return "Nice person"
case .SoLazy:
return "its so lazy person"
}
}
else
{
return "YourTextHere"
}
}
func typeImage(personTypeKey : String) -> String {
if PersonType.allKeys.contains(personTypeKey)
{
switch self {
case .Cool:
return "cool.png"
case .Nice:
return "img_nice.png"
case .SoLazy:
return "lazy.png"
}
}
else
{
return "YourImageHere"
}
}
}
答案 5 :(得分:1)
在Swift 5.1中,现在可以设置默认值。您的代码如下所示:
enum PersonType {
case cool(String = "cool")
case nice(String = "rude")
case soLazy(String = "so-lazy")
}
答案 6 :(得分:1)
我建议使用这种方法
public enum Result {
case passed(hint: String)
case failed(message: String)
static let passed: Self = .passed(hint: "")
}
let res: Result = Result.passed
答案 7 :(得分:0)
我想知道字典是否比这里的枚举更合适:
let dict = [
"Cool": "cool",
"Nice": "rude",
"SoLazy": "so-lazy"
]
let personType = "unknown"
let personDescription = dict[personType] ?? "Unknown"
减少打字,加快处理速度,更自然地处理默认案例,更容易扩展。
答案 8 :(得分:0)
回答您的问题:
public enum PersonType:String {
case Cool = "cool"
case Nice = "rude"
case SoLazy = "so-lazy"
static var `default`: PersonType { return .SoLazy }
public init(rawValue: RawValue) {
switch rawValue {
case PersonType.Cool.rawValue: self = .Cool
case PersonType.Nice.rawValue: self = .Nice
case PersonType.SoLazy.rawValue: self = .SoLazy
default: self = .default
}
}
public var description: String {
switch self {
case .Cool:
return "Cool person"
case .Nice:
return "Nice person"
case .SoLazy:
return "its so lazy person"
}
}
public var typeImage: String {
switch self {
case .Cool:
return "cool.png"
case .Nice:
return "img_nice.png"
case .SoLazy:
return "lazy.png"
}
}
}
现在,因为没有默认值可失败的初始化程序,请替换:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
}
使用:
personType = PersonType(rawValue: personTypeKey)
答案 9 :(得分:-1)
对于你的情况:
枚举的默认值:
我只是添加一个default
计算属性,
或者包括自定义初始化。
public enum PersonType:String {
case Cool = "cool"
case Nice = "rude"
case SoLazy = "so-lazy"
/// add a `default` computer property
public static var `default`: PersonType {
return .SoLazy
}
/// add an customize init function
public init(person: String? = nil) {
if let person = person {
switch person {
case "cool": self = .Cool
case "rude": self = .Nice
case "so-lazy": self = .SoLazy
default: self = .SoLazy
}
} else {
self = .SoLazy
}
}
public var description: String {
switch self {
case .Cool:
return "Cool person"
case .Nice:
return "Nice person"
case .SoLazy:
return "its so lazy person"
}
}
public var typeImage: String {
switch self {
case .Cool:
return "cool.png"
case .Nice:
return "img_nice.png"
case .SoLazy:
return "lazy.png"
}
}
}
使用:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
} else {
self.personType = PersonType.default
}
或者
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
} else {
self.personType = PersonType()
}
具有关联值的枚举的默认值:
public enum Gender {
case man
case woman
}
public enum PersonType {
case cool(Gender)
case nice(Gender)
case soLazy(Gender)
public static var `default`: PersonType {
return PersonType.make.soLazy()
}
public enum Builder {
public static func cool() -> PersonType {
return PersonType.cool(.woman)
}
public static func nice() -> PersonType {
return PersonType.nice(.woman)
}
public static func soLazy() -> PersonType {
return PersonType.soLazy(.woman)
}
}
public static var make: PersonType.Builder.Type {
return PersonType.Builder.self
}
public var description: String {
switch self {
case .cool(let gender):
switch gender {
case .man: return "Cool boy"
case .woman: return "Cool girl"
}
case .nice(let gender):
switch gender {
case .man: return "Nice boy"
case .woman: return "Nice girl"
}
case .soLazy(let gender):
switch gender {
case .man: return "its so lazy boy"
case .woman: return "its so lazy girl"
}
}
}
public var typeImage: String {
switch self {
case .cool(_):
return "cool.png"
case .nice(_):
return "img_nice.png"
case .soLazy(_):
return "lazy.png"
}
}
}
使用:
let onePersonType = PersonType.default
let anotherPersonType = PersonType.make.soLazy()
我在Ilya Puchka' blog找到了第二个案例解决方案。 它也在swift's proposal中提到过。