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
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
}
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")
}
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!
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.
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)}
0
1
99
Q2
enum Step: Int,CaseIterable {
case one, two=99, three
}
Step.allCases.forEach{print($0.rawValue)}
0
99
100
Q3
enum Step: Int,CaseIterable {
case one=12, two=11, three
}
Step.allCases.forEach{print($0.rawValue)}
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)}
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
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!!")
}
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)
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)
}
Kompilierungsfehler
error: MyPlayground.playground:2:6: error: recursive enum 'ArithmeticExpression' is not marked 'indirect'
enum ArithmeticExpression: CustomStringConvertible {
^
indirect
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!