Überprüfen Sie den Swift-Aufzählungstyp

Überblick

Dies ist ein Artikel für Anfänger. Auch wenn Sie kein Anfänger sind, können Sie etwas entdecken. Ich werde über die Aufzählung der Swift-Grammatik schreiben.

Betrieb mit Swift 5.3 bestätigt

Erstes Problem

Können Rohwert und zugehöriger Wert gleichzeitig in Swifts Aufzählung verwendet werden?

Wenn Sie dies wissen, müssen Sie diesen Artikel möglicherweise nicht speziell lesen.

enum Es wird als Aufzählungstyp bezeichnet. Mit Aufzählung und Groß- / Kleinschreibung definiert.

enum CompassPoint {
    case north
    case south
    case east
    case west
}

In Variable speichern

Variablen sind ** Singular **. Wenn Sie wissen, welcher Aufzählungstyp die Variable ist, können Sie den Typ wie ".east" weglassen.

var directionToHead = CompassPoint.north
directionToHead = .south

var directionToHeadLast: CompassPoint = .east

Switch In der Switch-Anweisung tritt ein Kompilierungsfehler auf, wenn nicht alle Fälle von Aufzählung abgedeckt sind. Sie können auch Standard verwenden.

switch directionToHead {
case .north, .east, .south, .west: print("direction")
}

switch directionToHead {
case .north, .east, .south: print("direction")
default: print("other")
}

Drehen Sie die Iteration

Durch Hinzufügen von CaseIterable können Sie das Element enum mit einer for-Anweisung drehen.

Es ist so


enum CompassPoint: CaseIterable {
    case north
    case south
    case east
    case west
}


CompassPoint.allCases.forEach{print($0)}

Dies gibt Folgendes aus:

north
south
east
west

Associated Values

Es ist möglich, jedem Element der Aufzählung einen Wert zu geben.


enum Appliance {
    case light(isOn: Bool)
    case airCon(degree: Int, isOn: Bool)
}

var appliance: Appliance
appliance = .light(isOn: true)
appliance = .airCon(degree: 28, isOn: true)

Wenn Sie es in einer Switch-Anweisung verwenden, können Sie den zugeordneten Wert mit let oder var abrufen.

switch appliance {
case .light(let isOn):
    print(isOn)
case .airCon(let degree, let isOn):
    print(isOn, degree)
}

Beachten Sie, dass das zuvor veröffentlichte Case Iterable nicht für Aufzählungen mit ** Associated Values ** verwendet werden kann!

Eine kleine Technik

Wenn der zugehörige Wert alle let oder alle var ist, wird er wie folgt multipliziert.


switch appliance {
case let .light(isOn):
    print(isOn)
case let .airCon(degree, isOn):
    print(isOn, degree)
}

Sie müssen nicht mehrere Let schreiben, indem Sie "Let" voranstellen!

Raw Values

Im Gegensatz zu zugeordneten Werten können Sie in jedem Fall von enum ** Werte eingeben, die zum Zeitpunkt des Schreibens ** fest sind.

enum Step: Int {
    case one = 1
    case two = 2
    case three = 3
}

print(Step.three.rawValue)

Dies zeigt 3 an.

enum Step: Int {
    case one, two, three
}

print(Step.one.rawValue)

Was wird das wohl zeigen?

Tatsächlich

0

Wird angezeigt.

Nur wenn es sich um den Rohwert von Int oder String handelt, wird der Wert ohne Erlaubnis eingegeben. Im Fall von Int tritt "0" in den ersten Fall ein und wird einzeln erhöht. Im Fall von String wird der Name des Falls selbst eingegeben.

Weitere Untersuchung

Lassen Sie uns mehr über Raw Value tun. Es wird Probleme verursachen, also raten wir mal die Ausgabezeichenfolge.

Q1

enum Step: Int,CaseIterable {
    case one, two, three=99
}

Step.allCases.forEach{print($0.rawValue)}
Q1 Antwort
0
1
99

Q2


enum Step: Int,CaseIterable {
    case one, two=99, three
}

Step.allCases.forEach{print($0.rawValue)}
Q2 Antwort
0
99
100

Q3


enum Step: Int,CaseIterable {
    case one=12, two=11, three
}

Step.allCases.forEach{print($0.rawValue)}
Q3 Antwort

Es liegt ein Kompilierungsfehler vor. Für drei wird 12 eingegeben, was für zwei ein Inkrement von 11 ist, aber ich werde wütend, weil dies mit eins abgedeckt ist.

Q4


enum Step: Int8,CaseIterable {
    case one, two=127, three
}

Step.allCases.forEach{print($0.rawValue)}

Q4 Antwort

Dies ist auch ein Kompilierungsfehler Int8 hat ein Maximum von 127, daher werde ich wütend, wenn die drei Werte in int8 überlaufen.

error: MyPlayground.playground:12:24: error: integer literal '128' overflows when stored into 'Int8'
    case one, two=127, three

Mit Rohwert initialisieren

Es kann von rawValue bis enum sein. Beachten Sie, dass wenn Sie einen Wert angeben, der nicht in enum enthalten ist, dieser ** nil ** ist!


enum Step: Int, CaseIterable {
    case one=1, two, three
}

Step(rawValue: 2) // two
Step(rawValue: 4) // nil

Mit anderen Worten, der Rückgabewert ist optional, wenn er mit rawValue initialisiert wird. Verwenden Sie beim Initialisieren mit rawValue die optionale Bindung

guard let step = Step(rawValue: 4) else {
    fatalError("undefined!!")
}

Können Rohwert und zugehöriger Wert gleichzeitig in Swifts Aufzählung verwendet werden?

Das ist das erste Problem.

Die Antwort lautet "kann"

Wenn Sie es normal gemacht haben, diesen Code


enum CompassPoint: String {
    case north(Int)
    case south(Int)
    case east(Int)
    case west(Int)
}

Ich erhalte einen Kompilierungsfehler.

'CompassPoint' declares raw type 'String', but does not conform to RawRepresentable and conformance could not be synthesized

In der Realität kann es jedoch verwaltet werden.

Die diesmal erläuterte Methode zum Schreiben des Rohwerts von enum wird als "Kurzschreibweise" bezeichnet. Es ist wie folgt geschrieben.


enum Test: String {
    case pass = "Yay!"
}

Voraussetzung für die Realisierung von RawValue ist die Einhaltung des Protokolls "RawRepresentable", das auch im obigen Kompilierungsfehler enthalten ist. Wenn der Fall mindestens einen zugeordneten Wert hat, entspricht die "Kurzschreibweise" automatisch nicht mehr "RawRepresentable". Sie können also den Rohwert und den zugehörigen Wert gleichzeitig verwenden, indem Sie die folgenden Schritte ausführen.

enum TestResult {
    case pass(Int)
    case fail(Int)
}

extension TestResult: RawRepresentable {
    typealias RawValue = String
    
    init?(rawValue: RawValue) {
        switch rawValue {
        case "Yay!": self = .pass(1)
        case "Es tut uns leid ...": self = .fail(0)
        default:
            return nil
        }
    }
    
    var rawValue: RawValue {
        switch self {
        case .pass: return "Yay!"
        case .fail: return "Es tut uns leid ..."
            
        }
    }
}

TestResult.pass(1).rawValue //Yay!
TestResult.fail(0).rawValue //Es tut uns leid ...

Beachten Sie, dass Sie beim Initieren den zugeordneten Wert eingeben müssen.

Schließlich ist die Art und Weise, den Rohwert der "Kurzhandnotation" zu schreiben, nur ein kurzer Ausdruck, und der Compiler scheint ihn wie oben als "Rohdarstellbar" zu definieren. (Referenz: Das RawRepresentable-Protokoll in Swift - Ole Begemann)

Rekursive Aufzählung

Wenn Sie reum rekursiv für einen zugeordneten Wert verwenden möchten, müssen Sie diesem Fall das indirekte Schlüsselwort hinzufügen.


enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression) //Rekursiv, weil das Argument hier sich selbst enthält
}

Indirekt kann auch an den Anfang der Aufzählung gebracht werden.

indirect enum ArithmeticExpression: CustomStringConvertible {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
}

Ohne indirekt?

Kompilierungsfehler

error: MyPlayground.playground:2:6: error: recursive enum 'ArithmeticExpression' is not marked 'indirect'
enum ArithmeticExpression: CustomStringConvertible {
     ^
indirect 

Ich habe versucht, für einen Moment eine Zeichenkette anzuzeigen

let expression = ArithmeticExpression.addition(.number(10), .addition(.number(1), .number(2)))

print(expression.description)

Ich möchte den Ausdruck im obigen Ausdruck als Zeichenfolge anzeigen. Ich habe versucht, die Zeichenfolge des Ausdrucks mit CustomStringConvertible rekursiv anzuzeigen.

enum ArithmeticExpression: CustomStringConvertible {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    
    var description: String {
        get {
            switch self {
            case .number(let num):
                return String(num)
            case .addition(let expr1, let expr2):
                return "\(expr1.description) + \(expr2.description)"
            }
        }
    }
}

Ist es so

10 + 1 + 2

Es wurde sicher angezeigt!

Zusammenfassung

Referenz

Recommended Posts

Überprüfen Sie den Swift-Aufzählungstyp
[Swift] Über den Aufzählungstyp
[Swift / Anfänger] Verwenden Sie Enum für die konservative Codierung