Значение по умолчанию для Enum in Swift

У меня есть 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"
    }
   }  

}

Проблема: я не знаю всех ключей типа человека, поэтому мне нужно обработать случай с типом персонализации по умолчанию и дать ему описание, будет ли он ключевым, как "ленивый" и образ по умолчанию.

скажем, я получаю этот результат от веб-службы:

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

Мне нужно иметь случай по умолчанию для обработки ключа "смешно"

вот как я инициализирую свое перечисление при разборе и создании объекта person:

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

Я хочу else или лучший подход для обработки случайных ключей в моем перечислении и дать им ключ как описание и образ по умолчанию.

Ответ 1

Другой подход, который работает в Swift 3 (может быть, 2, не знаю):

enum PersonType: String {
    case cool = "cool"
    case nice = "nice"
    case soLazy = "so-lazy"
    case other
}

let person = PersonType(rawValue: "funny") ?? .other

Лицевая переменная имеет тип PersonType.other в этом случае.

Недостатком этого является то, что вы не знаете строкового значения другого случая.

Ответ 2

Отбросьте необработанный тип и используйте 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, сохраняя при этом фактическое "неизвестное" значение для последующего использования.

Ответ 3

Это довольно близко, но я хотел бы иметь возможность сохранять значение, которое может быть связано с ним, вроде как с 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. Существует один оператор case для сопоставления имен, но с этого момента вы можете использовать имена и никогда не должны ссылаться на цифры.

Ответ 4

так:

init() {
    self = .Cool
}

Ответ 5

В Swift 5.1 теперь можно установить значения по умолчанию. Ваш код будет выглядеть так:

enum PersonType {
  case cool(String = "cool")
  case nice(String = "rude")
  case soLazy(String = "so-lazy")
}

Ответ 6

Попробуйте этот подход.

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

Ответ 7

Для вас:

Значение по умолчанию для Enum: Я просто добавляю свойство 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()
}

Значение по умолчанию для Enum со связанным значением:

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. А также он упоминается в быстрое предложение.

Ответ 8

Интересно, что словарь не подходит лучше, чем перечисление здесь:

let dict = [
    "Cool": "cool",
    "Nice": "rude",
    "SoLazy": "so-lazy"
]

let personType = "unknown"
let personDescription = dict[personType] ?? "Unknown"

Меньшая настройка, более быстрая обработка, более естественная обработка случая по умолчанию, более простое расширение.

Ответ 9

Чтобы ответить на ваш вопрос:

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)