ios Swift 中 Enum 的默认值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37731962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Default value for Enum in Swift
提问by iOSGeek
I have an 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"
}
}
}
The problem I don't know all the person type keys so I need to handle a default case of type person and to give it the description will be it's key like "so-lazy" and a default image.
问题我不知道所有的 person 类型键,所以我需要处理一个 person 类型的默认情况,并给它描述将是它的键,如“so-lazy”和默认图像。
let's say I get this result from the web service:
假设我从 Web 服务中得到了这个结果:
[
{
name: "john",
key: "cool"
},
{
name: "paul",
key: "funny"
}
]
I need to have a a default case to handle the key "funny"
我需要有一个默认情况来处理关键“有趣”
here is how I init my enum while parsing and creating person object:
这是我在解析和创建 person 对象时初始化我的枚举的方式:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
}
I want an else
or a better approach to handle the case of unknown keys in my enum, and give them the key as description and a default image.
我想要一种else
或更好的方法来处理枚举中未知键的情况,并为它们提供键作为描述和默认图像。
回答by Buddy
Another approach that works in Swift 3 (maybe 2, don't know):
另一种适用于 Swift 3 的方法(可能是 2,不知道):
enum PersonType: String {
case cool = "cool"
case nice = "nice"
case soLazy = "so-lazy"
case other
}
let person = PersonType(rawValue: "funny") ?? .other
The person variable is of type PersonType.other in this case.
在这种情况下,person 变量的类型为 PersonType.other。
The downside to this is that you don't know the raw string value of the .other case.
这样做的缺点是您不知道 .other 案例的原始字符串值。
回答by dasblinkenlight
Drop the raw type, and use enum
with associated value:
删除原始类型,并使用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)
}
}
}
The downside to dropping the raw type is that you must provide some logic for parsing the known enum
values. The upside, however, is that you can fit anything else into a single Unknown
case, while keeping the actual "unknown" value available for later use.
删除原始类型的缺点是您必须提供一些逻辑来解析已知enum
值。然而,好处是您可以将任何其他内容放入单个Unknown
案例中,同时保留实际的“未知”值以供以后使用。
回答by possen
This goes pretty close but I would like to be able to store the value that can be associated with it, kind of like you can with C.
这非常接近,但我希望能够存储可以与之关联的值,就像使用 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
Had to create a custom initializer, otherwise it is recursive. And it is still possible to create using the rawValue initializer by accident.
必须创建一个自定义初始化程序,否则它是递归的。并且仍然有可能意外地使用 rawValue 初始值设定项进行创建。
This however feels more Swifty, I removed the : Int
type specifier which allows you to use associated values, now the exceptional case that we don't do anything special is handled in the other
:
然而,这感觉更 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
With this I could get the actual value for an "other" error, and I can use the rawValue so it acts a lot like an Int based enum. There is the single case statement to map the names but from then on you can use the names and never need to refer to the numbers.
有了这个,我可以获得“其他”错误的实际值,并且我可以使用 rawValue 因此它的行为很像基于 Int 的枚举。有一个 case 语句来映射名称,但从那时起您可以使用名称而无需引用数字。
回答by William Hu
like so:
像这样:
init() {
self = .Cool
}
回答by Rui Peres
In Swift 5.1 it's now possible to set default values. Your code would look like this:
在 Swift 5.1 中,现在可以设置默认值。您的代码如下所示:
enum PersonType {
case cool(String = "cool")
case nice(String = "rude")
case soLazy(String = "so-lazy")
}
回答by Giuseppe Mazzilli
To answer your question:
回答你的问题:
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"
}
}
}
Now since having no failable initializer with default value replace your:
现在因为没有带有默认值的可失败初始化器替换你的:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
}
With:
和:
personType = PersonType(rawValue: personTypeKey)
回答by tdbit
This question is pretty old now and a lot has moved on in the Swift world. With Swift 5 I would recommend the approach below which involves creating a new initializer for the enum:
这个问题现在已经很老了,而且在 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
}
}
}
Use it like this:
像这样使用它:
self.personType = PersonType(personTypeKey)
Or like this:
或者像这样:
self.personType = nil
In either case, even if the value isn't valid for the PersonType
enum or it's just nil you will get a valid enum that's set to the default value of .SoLazy
在任何一种情况下,即使该值对PersonType
枚举无效或者它只是 nil,您也会获得一个有效的枚举,该枚举设置为 .SoLazy 的默认值
This is similar to several other approaches in this thread but instead of listing out all the possible valid values (which can be unwieldy if there are a lot of them) it uses a multiple guard let =
statement to guarantee it works.
这类似于该线程中的其他几种方法,但它没有列出所有可能的有效值(如果有很多可能会很笨拙),它使用 multipleguard let =
语句来保证它有效。
回答by Yehor Chernenko
I recommend using such an approach
我建议使用这种方法
public enum Result {
case passed(hint: String)
case failed(message: String)
static let passed: Self = .passed(hint: "")
}
let res: Result = Result.passed
回答by Yehor Chernenko
Try this approach.
试试这个方法。
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"
}
}
}
回答by JerryZhou
For you case:
对于你的情况:
Default Value of Enum:
I just add an default
computed property,
Or include an customize init.
Enum 的默认值:我只是添加了一个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"
}
}
}
To use:
使用:
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
} else {
self.personType = PersonType.default
}
Or
或者
if let personType = PersonType(rawValue:personTypeKey ?? "") {
self.personType = personType
} else {
self.personType = PersonType()
}
Default Value of Enum With Associated Value:
带有关联值的枚举的默认值:
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"
}
}
}
To use:
使用:
let onePersonType = PersonType.default
let anotherPersonType = PersonType.make.soLazy()
The second case solution I was found on Ilya Puchka' blog. And also it's mentioned in swift's proposal.
我在Ilya Puchka 的博客上找到了第二个案例解决方案。并且在swift 的提案中也提到了这一点。