Suche…


Bemerkungen

Wie bei Strukturen und im Gegensatz zu Klassen handelt es sich bei Enums um Werttypen, die beim Weitergeben nicht referenziert, sondern kopiert werden.

Weitere Informationen zu Enums finden Sie unter Die Swift-Programmiersprache .

Grundaufzählungen

Eine Aufzählung enthält eine Reihe verwandter Werte:

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

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

Aufzählungswerte können mit ihrem vollständig qualifizierten Namen verwendet werden. Sie können jedoch den Typnamen weglassen, wenn er abgeleitet werden kann:

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

Die grundlegendste Methode zum Vergleichen / Extrahieren von Aufzählungswerten besteht in einer switch Anweisung:

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
}

Einfache Aufzählungen sind automatisch Hashable , Equatable und haben String-Konvertierungen:

if dir == .down { ... }

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

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

Aufzählungen mit zugehörigen Werten

Aufzählungsfälle können eine oder mehrere Nutzdaten ( zugehörige Werte ) enthalten:

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

Die Nutzlast muss angegeben werden, wenn der Aufzählungswert instanziiert wird:

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

Die switch Anweisung kann den zugehörigen Wert extrahieren:

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

Eine Einzelfall-Extraktion kann mit if case :

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

Die guard case Syntax kann zur späteren Extraktion verwendet werden:

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

Aufzählungen mit zugehörigen Werten sind standardmäßig nicht Equatable . Die Implementierung des Operators == muss manuell erfolgen:

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
}

Indirekte Nutzlasten

Normalerweise können Aufzählungen nicht rekursiv sein (da sie unendlich viel Speicherplatz benötigen):

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

Mit dem indirect Schlüsselwort speichert das Enum seine Nutzdaten mit einer Ebene von Indirection, anstatt es inline zu speichern. Sie können dieses Schlüsselwort in einem einzelnen Fall verwenden:

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 funktioniert auch auf der gesamten Aufzählung und macht jeden Fall indirekt, wenn nötig:

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

Roh- und Hashwerte

Aufzählungen ohne Payloads können Rohwerte eines beliebigen Literaltyps haben:

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

Aufzählungen ohne bestimmten Typ machen die rawValue-Eigenschaft nicht verfügbar

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

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

Es wird angenommen, dass ganzzahlige Rohwerte bei 0 beginnen und monoton ansteigen:

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

String-Rohwerte können automatisch synthetisiert werden:

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

Ein Rohwert entspricht automatisch RawRepresentable . Mit .rawValue können Sie den entsprechenden Rohwert eines Aufzählungswerts .rawValue :

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

Sie können mit init?(rawValue:) auch eine Aufzählung aus einem Rohwert 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)")
}

Wenn Sie den Hashwert einer bestimmten Enumeration abrufen möchten, können Sie auf dessen Hashwert zugreifen. Der Hashwert gibt den Index der Enumeration ab Null zurück.

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

Initialisierer

Enums können benutzerdefinierte Init-Methoden haben, die nützlicher sein können als die Standardinitialisierung init?(rawValue:) . Aufzählungen können auch Werte speichern. Dies kann nützlich sein, um die Werte zu speichern, mit denen sie initialisiert wurden, und um diesen Wert später abzurufen.

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

Mit diesem Initialisierer können wir Folgendes tun:

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

Aufzählungen teilen viele Funktionen mit Klassen und Strukturen

Enums in Swift sind viel leistungsfähiger als einige ihrer Kollegen in anderen Sprachen, wie z. B. C. Sie teilen viele Features mit Klassen und Strukturen , z. B. Definieren von Initialisierern , berechneten Eigenschaften , Instanzmethoden , Protokollkonformitäten und Erweiterungen .

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

Verschachtelte Aufzählungen

Sie können Enumerationen ineinander verschachteln. Dadurch können Sie hierarchische Enumerationen strukturierter und klarer strukturieren.

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

Und du kannst es so benutzen:

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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow