Swift中Enum的默认值

我有一个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”和默认图像。

假设我从Web服务获得此结果:

 [ { name: "john", key: "cool" }, { name: "paul", key: "funny" } ] 

我需要有一个默认案例来处理关键的“搞笑”

这是我在解析和创建person对象时如何初始化我的枚举:

 if let personType = PersonType(rawValue:personTypeKey ?? "") { self.personType = personType } 

我想要一个else或更好的方法来处理枚举中未知键的情况,并给它们作为描述和默认图像的密钥。

删除原始类型,并使用带有关联值的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案例中,同时保持实际的“未知”值可供以后使用。

另一种在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案例的原始字符串值。

像这样:

 init() { self = .Cool } 

这非常接近但我希望能够存储可以与之关联的值,就像你可以用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处理:

 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的枚举。 有一个单一案例声明来映射名称,但从那时起,您可以使用名称,永远不需要参考数字。

试试这种方法。

 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" } } } 

我想知道字典是不是比这里的枚举更合适:

 let dict = [ "Cool": "cool", "Nice": "rude", "SoLazy": "so-lazy" ] let personType = "unknown" let personDescription = dict[personType] ?? "Unknown" 

减少打字,加快处理速度,更自然地处理默认案例,更容易扩展。

对于你的情况:

枚举的默认值 :我只是添加一个default计算属性,或者包含一个自定义init。

 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的博客上找到了第二个案例解决方案。 而且在swift的提案中也提到了它。