Quiero asociar dos primas valores de una enumeración de instancia (imagine que una enumeración que representan tipos de error, quiero Error.Teapot tener un tipo Int propiedad code con valor 418, y una Cadena de conjunto de propiedades a I'm a teapot.)

Nota la diferencia entre raw valores y valores asociados aquí—quiero que todos los Teapot instancias de tener un code de 418, yo no quiero un único valor asociado para cada Teapot instancia.

Existe una mejor manera de agregar calculada propiedades a la enumeración que switched en self para buscar el valor apropiado?

9 Comentarios

  1. 12

    No, una enumeración no puede tener varios valores sin procesar – tiene que ser un solo valor, la aplicación de la Equatable protocolo, y ser literal-convertible como se describe en el documentación.

    Creo que el mejor enfoque en su caso es utilizar el código de error como valor crudo, y una propiedad respaldado por una rellena estática diccionario con el código de error como clave y el texto como valor.

  2. 2

    No, usted no puede tener varios primas de los valores asociados con una enumeración.

    En su caso, usted podría tener el valor bruto sea igual al código, y tiene un valor asociado con la descripción. Pero creo que la calculada propiedades enfoque es la mejor opción aquí.

    • Un valor asociado con la descripción no sería correcto para lo que yo quiero. Todos Teapot instancias deben tener la misma cadena; yo uso un asociado de la Cadena de valor de si me quería conectar decir, una nota sobre la fuente de una determinada instancia de error.
  3. 2

    He creado una manera de simular este (No es diferente de lo que Marcos Crispino sugirió en su respuesta). Lejos de ser una solución perfecta, pero nos permite evitar los desagradables interruptor de casos para cada uno de los diferentes bienes que queremos obtener.

    El truco es usar una estructura como la de «propiedades» /data» titular y su uso como un RawValue en la enumeración de sí mismo.

    Tiene un poco de duplicación pero es servirme bien hasta ahora. Cada vez que desee agregar un nuevo enum caso, el compilador le recordará que debe llenar en el caso extra en el rawValue getter, que debería recordarle a actualizar la init? que recordar para crear la nueva propiedad estática de la estructura.

    Gist

    Código a la Esencia:

    enum VehicleType : RawRepresentable {
    struct Vehicle : Equatable {
    let name: String
    let wheels: Int
    static func ==(l: Vehicle, r: Vehicle) -> Bool {
    return l.name == r.name && l.wheels == r.wheels
    }
    static var bike: Vehicle {
    return Vehicle(name: "Bicycle", wheels: 2)
    }
    static var car: Vehicle {
    return Vehicle(name: "Automobile", wheels: 4)
    }
    static var bus: Vehicle {
    return Vehicle(name: "Autobus", wheels: 8)
    }
    }
    typealias RawValue = Vehicle
    case car
    case bus
    case bike
    var rawValue: RawValue {
    switch self {
    case .car:
    return Vehicle.car
    case .bike:
    return Vehicle.bike
    case .bus:
    return Vehicle.bus
    }
    }
    init?(rawValue: RawValue) {
    switch rawValue {
    case Vehicle.bike:
    self = .bike
    case Vehicle.car:
    self = .car
    case Vehicle.bus:
    self = .bus
    default: return nil
    }
    }
    }
    VehicleType.bike.rawValue.name
    VehicleType.bike.rawValue.wheels
    VehicleType.car.rawValue.wheels
    VehicleType(rawValue: .bike)?.rawValue.name => "Bicycle"
    VehicleType(rawValue: .bike)?.rawValue.wheels => 2
    VehicleType(rawValue: .car)?.rawValue.name => "Automobile"
    VehicleType(rawValue: .car)?.rawValue.wheels => 4
    VehicleType(rawValue: .bus)?.rawValue.name => "Autobus"
    VehicleType(rawValue: .bus)?.rawValue.wheels => 8
    • esto es f^&*ed hasta yo. Pero una especie de fresco.
    • Estás usando el interruptor de todos modos, y dos veces tan a menudo; y la adición de dos niveles adicionales de propiedades. Más de código para mantener, más código para analizar.
    • Sí, por dos propiedades no hay ningún triunfo. La victoria viene después de eso. Si usted tiene 10 propiedades (probablemente ese sería el olfato, pero es sólo para hacer un punto) que no necesitan de interruptores adicionales. 🙂
    • Pero sí, estoy de acuerdo en que la «f^&*ed up». 😀
  4. 1

    Una solución si usted quisiera tener muchas propiedades estáticas para un YourError podría ser para importar una lista de propiedades; no se pudo establecer el objeto de raíz a un diccionario, con su enumeración valor crudo, como la clave para cada objeto, permitiéndole recuperar fácilmente estática estructurado de datos para el objeto.

    Este tiene un ejemplo de la importación y el uso de un plist: http://www.spritekitlessons.com/parsing-a-property-list-using-swift/

    Que podría ser demasiado para el, simplemente, un error en la descripción, por lo que sólo podría utilizar un duro función estática con un interruptor para la declaración de su enumeración de los valores, que devuelve la cadena de error que usted necesita. Simplemente coloque la función estática de la misma .swift archivo como su enumeración.

    Por ejemplo,

    static func codeForError(error : YourErrorType) -> Int {
    switch(error) {
    case .Teapot:
    return "I'm a Teapot"
    case .Teacup:
    return "I'm a Teacup"
    ...
    default:
    return "Unknown Teaware Error"
    }
    }

    Esto tiene la ventaja (en comparación con el .plist solución) de una mejor capacidad de localización. Sin embargo, una .plist sólo podría contener una clave que se utiliza para la recuperación de la correcta localización, en lugar de una cadena de errores, para este propósito.

  5. 1

    Tiene un par de opciones. Pero ninguno de ellos implican valores sin procesar. Raw valores no sólo son la herramienta adecuada para la tarea.

    Opción 1 (muy bueno): Valores Asociados

    Yo personalmente recomiendo en contra de que exista más de un valor asociado por enum caso. Valores asociados debe estar muerto obvio (ya que no se tienen argumentos/nombres), y tener más de una gran enturbia el agua.

    Que dijo, es algo que el lenguaje permite hacer. Esto permite que en cada caso se define de manera diferente, si que era algo que necesitaba. Ejemplo:

    enum ErrorType {
    case teapot(String, Int)
    case skillet(UInt, [CGFloat])
    }

    Opción 2 (mejor): Tuplas! Y las propiedades de!

    Las tuplas son una gran característica de Swift, porque ellos te dan el poder de la creación ad-hoc tipos. Eso significa que usted puede definir en línea. Dulce!

    Si cada uno de los tipos de error que se va a tener un código y una descripción, entonces usted podría tener una calculada info propiedad (esperemos que con un nombre mejor?). Ver más abajo:

    enum ErrorType {
    case teapot
    case skillet
    var info: (code: Int, description: String) {
    switch self {
    case .teapot:
    return (418, "Hear me shout!")
    case .skillet:
    return (326, "I'm big and heavy.")
    }
    }
    }

    Llamar a esto sería mucho más fácil porque usted podría utilizar sabroso sintaxis de punto:

    let errorCode = myErrorType.info.code

  6. 0

    Esto no particularmente responder a su pregunta, que estaba pidiendo a encontrar una mejor manera de switching a través de self para buscar el valor apropiado pero esta respuesta aún puede ser útil para alguien que busca en el futuro que necesita una forma sencilla de obtener una cadena a partir de una enumeración que se define como de tipo entero.

    enum Error: UInt {
    case Teapot = 418
    case Kettle = 419
    static func errorMessage(code: UInt) -> String {
    guard let error = Error(rawValue: code) else {
    return "Unknown Error Code"
    }
    switch error {
    case .Teapot:
    return "I'm a teapot!"
    case .Kettle:
    return "I'm a kettle!"
    }
    }
    }

    De esta manera, podemos obtener la errorMessage dos maneras:

    1. Con un número entero (por ejemplo. que se devuelve un código de error de un servidor)
    2. Con un valor de enumeración (el rawValue definimos de la enumeración)

    Opción 1:

    let option1 = Error.errorMessage(code: 418)
    print(option1)  //prints "I'm a teapot!"

    Opción 2:

    let option2 = Error.errorMessage(code: Error.Teapot.rawValue)
    print(option2)  //prints "I'm a teapot!"    
  7. 0

    En las versiones modernas de Swift, es posible obtener la cadena de valor de una enumeración caso de la etiqueta, incluso sin que la enumeración sea declarado con un : String rawValue.

    Cómo obtener el nombre de valor de enumeración de Swift?

    Así que ya no hay una necesidad de definir y mantener una función de conveniencia que cambia en cada caso para devolver una cadena literal. Además, esto funciona automáticamente para cualquier enum, incluso si no hay raw-tipo de valor es especificado.

    Esto, al menos, le permite tener «múltiples valores sin procesar» por la existencia de un real : Int rawValue así como la cadena que se utiliza como el caso de la etiqueta.

  8. 0

    Por principio, suponiendo que se desea almacenar un código y un mensaje, usted puede utilizar una estructura para RawValue

    struct ErrorInfo {
    let code: Int
    let message: String
    }

    Siguiente paso es definir el enum como RawRepresentable, y el uso ErrorInfo como el valor en crudo:

    enum MyError: RawRepresentable {
    typealias RawValue = ErrorInfo
    case teapot

    Lo que queda es el mapa entre las instancias de MyError y ErrorInfo:

    static private let mappings: [(ErrorInfo, MyError)] = [
    (ErrorInfo(code: 418, message: "I'm a teapot"), .teapot)
    ]

    Con el anterior, vamos a construir la definición completa de la enumeración:

    enum MyError: RawRepresentable {
    static private let mappings: [(ErrorInfo, MyError)] = [
    (ErrorInfo(code: 418, message: "I'm a teapot"), .teapot)
    ]
    case teapot
    init?(rawValue: ErrorInfo) {
    guard let match = MyError.mappings.first(where: { $0.0.code == rawValue.code && $0.0.message == rawValue.message}) else {
    return nil
    }
    self = match.1
    }
    var rawValue: ErrorInfo {
    return MyError.mappings.first(where: { $0.1 == self })!.0
    }
    }

    Algunas notas:

    • usted podría utilizar sólo el código de error de coincidencia, sin embargo, esto podría resultar incoherente raw valores si los mensajes se diferencian
    • la cantidad de código repetitivo obligados a tener crudo valores de algún tipo personalizado posible que no de resultado de los beneficios de la utilización de valores asociados.
  9. 0

    Posible evitar puede asociar funciones personalizadas con enum

     enum ToolbarType : String{
    case Case = "Case", View="View", Information="Information"
    static let allValues = [Case, View, Information]
    func ordinal() -> Int{
    return ToolbarType.allValues.index(of: self)!
    }
    }

    Puede ser utilizado como

     for item in ToolbarType.allValues {
    print("\(item.rawValue): \(item.ordinal())")
    }

    Salida

    Case: 0
    View: 1
    Information: 2

    Posiblemente, puede tener funciones adicionales para asociar un tipo enum a diferentes valores de

Dejar respuesta

Please enter your comment!
Please enter your name here