Default value for Enum in Swift

前端 未结 11 1854
南旧
南旧 2020-12-31 07:30

I have an enum :

public enum PersonType:String {

 case Cool                       = \"cool\"
 case Nice                       = \"rude\"
 case          


        
相关标签:
11条回答
  • 2020-12-31 07:31

    In Swift 5.1 it's now possible to set default values. Your code would look like this:

    enum PersonType {
      case cool(String = "cool")
      case nice(String = "rude")
      case soLazy(String = "so-lazy")
    }
    
    0 讨论(0)
  • 2020-12-31 07:32

    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)
    
    0 讨论(0)
  • 2020-12-31 07:33

    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:

    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

    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.

    0 讨论(0)
  • 2020-12-31 07:34

    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
    
    0 讨论(0)
  • 2020-12-31 07:35

    like so:

    init() {
        self = .Cool
    }
    
    0 讨论(0)
  • 2020-12-31 07:45

    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.

    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.

    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:

    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.

    0 讨论(0)
提交回复
热议问题