2016-06-09 6 views
4

У меня есть enum:Значение по умолчанию для Enum в Swift

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

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

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

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

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

ответ

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

С вашим подходом Как создать перечисление с неизвестным ключом – iOSGeek

+0

@iOSGeek Обновленный ответ, пожалуйста, проверьте. –

10

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

+0

Кажется, что это может быть хороший подход, но как создавать новые перечисления при разборе и иметь разные ключи, известные и неизвестные. – iOSGeek

+0

@iOSGeek Вызвать 'PersonType.parse (key)', он выдает правильное значение «enum». Обратите внимание на последнее изменение. – dasblinkenlight

+0

Я приведу все случаи перечисления связанного значения '(String, UIImage)' есть ли способ объявить это глобально и дать им теги, например '(typeName: String, imageType: UIImage)', чтобы сделать код более красивым? – iOSGeek

0

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

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

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

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

+0

, что о каждом типе имеет изображение, возможно, позже другое var, поэтому словарь не является подходит для моего случая – iOSGeek

+0

В этом случае вы не будете использовать словарь [String: String], но [String: (String, String)], [String: [String]] или [String: Custom Struct] – MirekE

12

Другой подход, который работает в 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 в этом случае.

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

3

так:

init() { 
    self = .Cool 
} 
+0

Это самый чистый способ . 'self' является изменяемым для типов значений. – user1046037

-1

Для вас дел:

По умолчанию Значение 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" 
     } 
    } 

} 

Применение:

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

} 

Применение:

let onePersonType = PersonType.default 
let anotherPersonType = PersonType.make.soLazy() 

Второе решение для решения было найдено по Ilya Puchka' blog. И также упоминается в swift's proposal.

+1

Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответы только для ссылок могут стать недействительными, если связанная страница изменяется - [Из обзора] (/ review/low-quality-posts/16136387) –

+1

@ KurtVandenBranden обновлен. – JerryZhou

1

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

Смежные вопросы