Swift中Enum的默认值

时间:2016-06-09 16:52:35

标签: ios swift data-structures enums swift2

我有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或更好的方法来处理枚举中未知密钥的情况,并为它们提供密钥作为描述和默认图像。

10 个答案:

答案 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中提到过。