Значение по умолчанию для 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)