Buscar..


Observaciones

Al igual que las estructuras y a diferencia de las clases, las enumeraciones son tipos de valor y se copian en lugar de hacer referencia cuando se pasan.

Para obtener más información sobre las enumeraciones, consulte El lenguaje de programación Swift .

Enumeraciones basicas

Una enumeración proporciona un conjunto de valores relacionados:

enum Direction {
    case up
    case down
    case left
    case right
}

enum Direction { case up, down, left, right }

Los valores de enumeración se pueden usar por su nombre completo, pero puede omitir el nombre de tipo cuando se puede inferir:

let dir = Direction.up
let dir: Direction = Direction.up
let dir: Direction = .up

// func move(dir: Direction)...
move(Direction.up)
move(.up)

obj.dir = Direction.up
obj.dir = .up

La forma más fundamental de comparar / extraer valores de enumeración es con una instrucción de switch :

switch dir {
case .up:
    // handle the up case
case .down:
    // handle the down case
case .left:
    // handle the left case
case .right:
    // handle the right case
}

Las enumeraciones simples son automáticamente Hashable , Equatable y tienen conversiones de cadena:

if dir == .down { ... }

let dirs: Set<Direction> = [.right, .left]

print(Direction.up)  // prints "up"
debugPrint(Direction.up)  // prints "Direction.up"

Enums con valores asociados.

Los casos de enumeración pueden contener una o más cargas útiles ( valores asociados ):

enum Action {
    case jump
    case kick
    case move(distance: Float)  // The "move" case has an associated distance
}

La carga útil debe proporcionarse al instanciar el valor de enumeración:

performAction(.jump)
performAction(.kick)
performAction(.move(distance: 3.3))
performAction(.move(distance: 0.5))

La instrucción switch puede extraer el valor asociado:

switch action {
case .jump:
    ...
case .kick:
    ...
case .move(let distance):  // or case let .move(distance):
    print("Moving: \(distance)") 
}

Una extracción de un solo caso se puede hacer usando el if case :

if case .move(let distance) = action {
    print("Moving: \(distance)") 
}

La sintaxis del guard case se puede utilizar para la extracción posterior del uso:

guard case .move(let distance) = action else {
    print("Action is not move")
    return
}

Las enumeraciones con valores asociados no son Equatable de forma predeterminada. La implementación del operador == debe hacerse manualmente:

extension Action: Equatable { }

func ==(lhs: Action, rhs: Action) -> Bool {
    switch lhs {
    case .jump: if case .jump = rhs { return true }
    case .kick: if case .kick = rhs { return true }
    case .move(let lhsDistance): if case .move (let rhsDistance) = rhs { return lhsDistance == rhsDistance }
    }
    return false
}

Cabida indirecta

Normalmente, las enumeraciones no pueden ser recursivas (porque requerirían almacenamiento infinito):

enum Tree<T> {
    case leaf(T)
    case branch(Tree<T>, Tree<T>)  // error: recursive enum 'Tree<T>' is not marked 'indirect'
}

La palabra clave indirect hace que la enumeración almacene su carga útil con una capa de direccionamiento indirecto, en lugar de almacenarla en línea. Puede utilizar esta palabra clave en un solo caso:

enum Tree<T> {
    case leaf(T)
    indirect case branch(Tree<T>, Tree<T>)
}

let tree = Tree.branch(.leaf(1), .branch(.leaf(2), .leaf(3)))

indirect también funciona en toda la enumeración, haciendo que cualquier caso sea indirecto cuando sea necesario:

indirect enum Tree<T> {
    case leaf(T)
    case branch(Tree<T>, Tree<T>)
}

Valores crudos y hash

Las enumeraciones sin carga útil pueden tener valores sin procesar de cualquier tipo literal:

enum Rotation: Int {
    case up = 0
    case left = 90
    case upsideDown = 180
    case right = 270
}

Las enumeraciones sin ningún tipo específico no exponen la propiedad rawValue

enum Rotation {
    case up
    case right
    case down
    case left
}

let foo = Rotation.up
foo.rawValue //error

Se asume que los valores brutos enteros comienzan en 0 y aumentan monótonamente:

enum MetasyntacticVariable: Int {
    case foo  // rawValue is automatically 0
    case bar  // rawValue is automatically 1
    case baz = 7
    case quux  // rawValue is automatically 8
}

Los valores en bruto de la cadena se pueden sintetizar automáticamente:

enum MarsMoon: String {
    case phobos  // rawValue is automatically "phobos"
    case deimos  // rawValue is automatically "deimos"
}

Una enumeración en bruto se ajusta automáticamente a RawRepresentable . Puede obtener el valor bruto correspondiente de un valor de enumeración con .rawValue :

func rotate(rotation: Rotation) {
    let degrees = rotation.rawValue
    ...
}

También puede crear una enumeración a partir de un valor en bruto usando init?(rawValue:) :

let rotation = Rotation(rawValue: 0)  // returns Rotation.Up
let otherRotation = Rotation(rawValue: 45)  // returns nil (there is no Rotation with rawValue 45)

if let moon = MarsMoon(rawValue: str) {
    print("Mars has a moon named \(str)")
} else {
    print("Mars doesn't have a moon named \(str)")
}

Si desea obtener el valor de hash de una enumeración específica, puede acceder a su valor de hash, el valor de hash devolverá el índice de la enumeración comenzando desde cero.

let quux = MetasyntacticVariable(rawValue: 8)// rawValue is 8
quux?.hashValue //hashValue is 3

Inicializadores

Las enumeraciones pueden tener métodos personalizados de inicio que pueden ser más útiles que el init?(rawValue:) predeterminado init?(rawValue:) . Enums también puede almacenar valores también. Esto puede ser útil para almacenar los valores con los que se inicializaron y recuperar ese valor más adelante.

enum CompassDirection {
    case north(Int)
    case south(Int)
    case east(Int)
    case west(Int)

    init?(degrees: Int) {
        switch degrees {
        case 0...45:
            self = .north(degrees)
        case 46...135:
            self = .east(degrees)
        case 136...225:
            self = .south(degrees)
        case 226...315:
            self = .west(degrees)
        case 316...360:
            self = .north(degrees)
        default:
            return nil
        }
    }
    
    var value: Int = {
        switch self {
            case north(let degrees):
                return degrees
            case south(let degrees):
                return degrees
            case east(let degrees):
                return degrees
            case west(let degrees):
                return degrees
        }    
    }
}

Usando ese inicializador podemos hacer esto:

var direction = CompassDirection(degrees: 0) // Returns CompassDirection.north
direction = CompassDirection(degrees: 90) // Returns CompassDirection.east
print(direction.value) //prints 90
direction = CompassDirection(degrees: 500) // Returns nil

Las enumeraciones comparten muchas características con clases y estructuras

Las enumeraciones en Swift son mucho más poderosas que algunas de sus contrapartes en otros idiomas, como C. Comparten muchas características con clases y estructuras , como la definición de inicializadores , propiedades computadas , métodos de instancia , conformidades de protocolo y extensiones .

protocol ChangesDirection {
    mutating func changeDirection()
}

enum Direction {
    
    // enumeration cases
    case up, down, left, right
    
    // initialise the enum instance with a case
    // that's in the opposite direction to another
    init(oppositeTo otherDirection: Direction) {
        self = otherDirection.opposite
    }
    
    // computed property that returns the opposite direction
    var opposite: Direction {
        switch self {
        case .up:
            return .down
        case .down:
            return .up
        case .left:
            return .right
        case .right:
            return .left
        }
    }
}

// extension to Direction that adds conformance to the ChangesDirection protocol
extension Direction: ChangesDirection {
    mutating func changeDirection() {
        self = .left
    }
}

var dir = Direction(oppositeTo: .down) // Direction.up

dir.changeDirection() // Direction.left

let opposite = dir.opposite // Direction.right

Enumeraciones anidadas

Puede anidar enumeraciones una dentro de otra, esto le permite estructurar enumeraciones jerárquicas para ser más organizadas y claras.

enum Orchestra {
    enum Strings {
        case violin
        case viola
        case cello
        case doubleBasse
    }
    
    enum Keyboards {
        case piano
        case celesta
        case harp
    }
    
    enum Woodwinds {
        case flute
        case oboe
        case clarinet
        case bassoon
        case contrabassoon
    }
}

Y puedes usarlo así:

let instrment1 = Orchestra.Strings.viola
let instrment2 = Orchestra.Keyboards.piano


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow