The original address

Enumerations are a generic type defined for a set of related values, and the Swift enumeration is very powerful, making it more applicable to a wide range of scenarios than OC enumerations. In this article, we’ll look at the syntax and capabilities of enUms.

The enumeration of grammar

Enumeration is introduced using the enum keyword, whose entire definition is enclosed in a pair of braces:

enum CompassPoint {
    case north
    case south
    case east
    case west
}
Copy the code

Unlike C and Objective-C, Swift enumerators are not assigned a default integer value when they are created.

Enumerator traversal

Make the enumeration follow the CaseIterable protocol. Swift generates an allCases property that returns a collection of all members of the enumeration.

enum Beverage: CaseIterable {
    case coffee, tea, juice
}

for beverage in Beverage.allCases {
    print(beverage)
}

// coffee
// tea
// juice
Copy the code

The associated values

Associated values are a great way to attach additional information to an enumeration member. The Swift enumeration can store any type of associated value, as shown in the following example:

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

Copy the code

The code above defines an enumeration type named Barcode, where one member UPC has an associated value of type (Int, Int, Int, Int) and the other member qrCode has an associated value of type String.

Associated values can be accessed through pattern matching, as shown in the following example:

var productBarcode = .qrCode("ABCDEFGHIJKLMNOP") switch productBarcode { case let .upc(numberSystem, manufacturer, product, check): print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).") case let .qrCode(productCode): Print ("QR code: \(productCode).")} "QR code: ABCDEFGHIJKLMNOP.Copy the code

Detailed use of pattern matching will be covered in a later article.

The original value

Enumerators can be prepopulated with default values, which are called primitive values. Note: The primitive values must be of the same type.

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}
Copy the code

By default, Swift supports only four types of enumerated values: integer, floating point, string, and Boolean. If you want to support more types of enumerated values, you need to implement the specified protocol, which will be covered in a later article.

Implicit assignment of the original value

Swift can automatically assign values for you when the original values used are integers or strings.

  • When the original value used is an integer, the implicitly assigned value is incremented by one at a time. If the first enumerator does not set a raw value, its default raw value is 0.
enum Planet: Int {case mercury = 1, Venus, earth, Mars, Jupiter, Saturn, Uranus, Neptune} The implicit raw value for planet.Venus is 2, and so on.Copy the code
  • When a string is used as the original value of an enumerator, the implicit original value of each enumerator is the name of that member.
// CompassPoint. South has the implicit original value south, and so on.Copy the code

The rawValue of an enumeration member can be accessed using the rawValue attribute:

Let earthsOrder = Planet. Earth. RawValue / / earthsOrder value of 3 let sunsetDirection = CompassPoint. West. RawValue / / SunsetDirection value for the "west"Copy the code

Initialize the enumeration instance with the original value

If a rawValue is used when defining an enumeration, an initialization method is automatically generated that takes a rawValue parameter of the rawValue type:

Let possiblePlanet = Planet(rawValue: 7) // possiblePlanet is of type like Planet? Value is the Planet UranusCopy the code

The primitive value constructor is a failable constructor because not every primitive value has a corresponding enumerator, so its return type is optional.

Recursive enumeration

A recursive enumeration is an enumeration type that is used as an associated value by one or more of its members. Prefix an enumeration member with the indirect keyword to indicate that the member is recursive:

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
Copy the code

An enumeration type can also be preceded by an indirect to indicate that all its members are recursive:

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}
Copy the code

Its use is as follows:

let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) func evaluate(_ expression: ArithmeticExpression) -> Int { switch expression { case let .number(value): return value case let .addition(left, right): return evaluate(left) + evaluate(right) case let .multiplication(left, right): Return evaluate(left) * evaluate(right) // (5 + 4) * 2}} print(evaluate(product)Copy the code

Nested enumeration

Swift allows the nesting of enumerations, and when we use it, we need to make sure that one enumeration type is subordinate to another enumeration type, otherwise it will cause semantic confusion. Here’s an example:

enum Character { enum Weapon { case Bow case Sword case Lance case Dagger } enum Helmet { case Wooden case Iron case Diamond} case Thief case Warrior case Knight} let character = character.Thief let weapon = Character.Weapon.Bow let helmet = Character.Helmet.IronCopy the code

Instead of entering such a long hierarchy each time you access nested enumerators, you can access them directly using a convenient method like this:

func strength(of character: Character, 

              with weapon: Character.Weapon, 

              and armor: Character.Helmet) {

}

strength(of: .thief, with: .bow, and: .wooden)
Copy the code

Contains the enumeration

You can also embed enumerations in structures or classes. Continuing with the previous example:

struct Character {

    enum CharacterType {

     case thief

     case warrior

     case knight

   }

   enum Weapon {

     case bow

     case sword

     case lance

     case dagger

   }

   let type: CharacterType

   let weapon: Weapon

}

let warrior = Character(type: .warrior, weapon: .sword)
Copy the code

Methods and Properties

Swift enumeration types can attach methods and attributes:

methods

enum Transportation {
   case car(Int)
   case train(Int)

    func distance() -> String {
     switch self {
     case .car(let miles): return "\(miles) miles by car"
     case .train(let miles): return "\(miles) miles by train"
     }
   }
}
Copy the code

The main difference from a structure or class type is that you can use self in a method to evaluate the output.

attribute

Note: Adding storage attributes is not allowed in Swift, the following code will compile an error:

enum Device {
   case iPad
   case iPhone
   
   let introduced: Int // Enums must not contain stored properties
}
Copy the code

You should use calculated properties like this:

enum Device {
    case iPad,
    case iPhone

    var introduced: Int {
        switch self {
        case .iPhone: return 2007
        case .iPad: return 2010
     }
  }
}
Copy the code

A static method

Static methods are methods that can be invoked by a type name rather than a specific instance of a type. Examples are as follows:

enum Device {
    static var newestDevice: Device {
        return .appleWatch
    }

    case iPad,
    case iPhone
    case appleWatch
}
Copy the code

Variable method

Declare a method as a mutable method using the mutating keyword, where an instance of self can be modified, as shown in the following example:

enum TriStateSwitch {
    case off, low, bright
    mutating func next() {
        switch self {
        case .off:
            self = low
        case .low:
            self = .bright
        case high:
            self = off
        }
    }
}

var ovenLight = TriStateSwitch.low

ovenLight.next()
// ovenLight is now equal to .bright

ovenLight.next()
// ovenLight is now equal to .off
Copy the code

summary

Enumerations declare types that are finite collections of possible states and can have added value. Enumerations can define any organized data hierarchically through embedding, methods, associated values, and pattern matching.

Reference:

  1. Appventure. Me/guides/adva…

2. Docs.swift.org/swift-book/…