The enumeration

Enumerated values are one of the most common types in our development process, and the actual type of an enumerated value in OC is NSInterge. In Swift, enumerations are given more and more flexible uses, and knowing how to use enumerations makes our code cleaner and more logical.

Swfit uses key subenums to declare an enumerated type.

enum OSCardType {

    case OSCardTypeOne

    case OSCardTypeTwo

    case OSCardTypeThree

}
Copy the code

Enumerations in Swift are very flexible and do not need to provide a value for every member of the enumeration. If a value (called a “primitive” value) is to be supplied to each enumerator, the value can be a string, a character, an arbitrary integer value, or a floating-point type.

enum OSDeviceCode: String {

    case OSDeviceCodeLight = "light"

    case OSDeviceCodeAirConditioner = "airConditioner"

}
Copy the code

RawValue can also be inferred by the compiler, which builds on Swift’s type inference mechanism

enum OSDayOfWeek: Int {

    case mon, tue, wed, thu, fri = 10, sat, sun

}
Copy the code

Mon = 0, ture = 1… Sat = 11, Sun = 12. If it is a String, rawValue defaults to an enumerated String.

The associated values

In addition to the above usage, enumerated values in Swift can carry more information to express more complex cases. Several associated values can be followed.

enum OSShape {
    case circle(redious: Double)
    case ractange(width: Double, height: Double)}Copy the code

When comparing patterns, note that the case of the Swift enumeration value needs to match all enumeration types, otherwise the compiler will report an error. When patterns with associated values are matched, the associated values appear as parameters.

func func1(a) {
        
        let cricle = OSShape.circle(redious: 10.0)
        
        switch cricle {
        case .circle(let circel):
            print(circel)
        case .ractange(let width, let height):
            print(width, height)
        }
    }
Copy the code

Enumeration size of memory

Enumerations are value types that are stored on the stack. There are two storage types: no-payload enum and single-payload enum.

You can print to see the size of the enumeration.

func func2(a) {

        print(MemoryLayout<OSCardType>.size)

        

        var card1 = OSCardType.OSCardTypeOne

        var card2 = OSCardType.OSCardTypeTwo

        print(card1,card2)

    }
Copy the code

Let’s move on to the size of memory with associated values.

enum SingleEnum1 {
        case One(isgood: Bool)
        case Two
        case Three
    }
    
    enum SingleEnum2 {
        case One(age: Int)
        case Two
        case Three
    }
    
    func func3(a) {
        print(MemoryLayout<SingleEnum1>.size)
        print(MemoryLayout<SingleEnum2>.size)
    }
Copy the code

Output 1, 9

Note here: SingleEnum1 is memory optimized to save on memory costs. Bool is actually stored in 1BITE, and the rest of the bits are used to store enumeration information. There’s a lot of data on the web that says that the size of an enumeration is equal to the memory of the largest association type plus the memory of the enumeration value, except for Bool. Very easy to miss. The corresponding description can also be found in the source code.

If the storage space is sufficient for the associated values, the load size is the same as the enumeration values.

Indeirect keyword

Analysis: the size of the value type is determined at compile time, and the above “nesting” method does not determine the memory size. We use the compiler’s modification method.

indirect enum BinaryTree<T> {
        case empty
        case node(left: BinaryTree, right: BinaryTree, value: T)}Copy the code
func func4(a) {
        var node = BinaryTree<Int>.node(left: BinaryTree<Int>.empty, right: BinaryTree<Int>.empty, value: 1)
        print(node)
        print(MemoryLayout<BinaryTree<Int>>.size)
        print(MemoryLayout<BinaryTree<Int>>.stride)
    }
Copy the code

Output bit 8 8, go ahead and print the address using LLDB.

This is when found when usedindirectAfter the keyword modifier, the system allocates space in the heap for the enumeration.

An optional value

Optional values are ubiquitous throughout our SWIFT programming, designed primarily for security purposes. Optional values are also implemented through enumerations.

class InFuncRoom {
          var roomId: String?
       }
Copy the code

You can also write:

class InFuncRoom {
// var roomId: String?
            var roomId: Optional<String> = nil
        }
Copy the code

Click Optional to see the implementationObviously the optional value is an enumeration.

Take an example of using something like this to experience the use of optional values.

Title: Remove all even numbers from an array.

// Implement the optional values yourself
    func func6(a) {
        var array = [1.2.3.4.5.6]
        for value in array {
            let optional = getOddValue(value)
            switch optional {
            case .some(let ele):
                array.remove(at: array.firstIndex(of: ele)!)
                print(ele)
            default:
                print("not exit")}}print(array);
    }
    
    func getOddValue(_ value: Int) -> MyOptional<Int> {
        if value % 2 = = 0 {
            return .some(value)
        } else {
            return .none
        }
    }
Copy the code

Unpack the

If we use a switch case for each of the optional values, which would be tedious to write, we can use an if let to bind the optional values (unpack).

    func func7(a) {
        var name: String? = "hahaha"
        if let name = name {
            print(name)
        }
        name = nil
        if let name = name {
            print(name)
        }  
    }
Copy the code

In addition to using the if let to handle optional values, we can also use the Gurad let to simplify our code. Let’s look at a specific example.

The guard let is the opposite of the if let. The guard let guard must have a value. If not, return directly. If you use an if let to create a branch layer out of thin air, guard lets are a way to lower the branch level

Operator overloading

struct Vector {
  let x: Int
  let y: Int
}

extension Vector {
  static func + (fistVector: Vector.secondVector: Vector) -> Vector {
    return Vector(x:  fistVector.x + secondVector.x, y: fistVector.y + secondVector.y)
  }

  static prefix func - (vector: Vector) -> Vector {
    return Vector(x: -vector.x, y: -vector.y)
  }

  static func - (fistVector: Vector.secondVector: Vector) -> Vector {
    return fistVector + -secondVector
  }

}
Copy the code
func func6(a) {
        let x = Vector(x: 10, y: 20)
        let y = Vector(x: 80, y: 50)
        let z = x + y
        print(z)
    }
Copy the code