본문 바로가기

Swift 문서 탐방

[Swift 문서 탐방] Enumerations

참고사이트

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations#Initializing-from-a-Raw-Value (Swift 공식 문서 - Enumerations)

Enumerations

Enum은 관련된 값들을 한 그룹으로 묶어놓은 타입을 의미하며, 이 관련된 값들을 Type-safe 하게 사용할 수 있습니다.

여기서 관련된 값의 타입은 String, Character, Interger, Float 등의 다양한 타입이 될 수 있습니다.(Raw Value)

또한, Enum은 각각의 다른 케이스 값과 함께 저장될 모든 유형의 연관된 값(Associated Value)를  지정할 수 있습니다. 

마지막으로 Enum은 클래스의 기능인 연산 프로퍼티, 메서드, 초기화 구문을 가질 수 있고, 확장 및 프로토콜 준수도 지원해 다양한 기능을 구현할 수 있습니다.

Enumeration Syntax

Enum은 enum 키워드로 시작하고 전체 정의를 중괄호 쌍 안에 넣습니다.

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

 

Swift Enum 케이스는 C 및 Objective-C와 같은 언어와 달리 기본적으로 정수 값이 설정되지 않습니다. 위의 CompassPoint 예에서 north, south, east 및 west는 암묵적으로 0, 1, 2 및 3과 같지 않습니다. 대신 다른 Enum 케이스는 명시적으로 정의된 CompassPoint 유형이 있는 자체 값입니다.

Matching Enumeration Values with a Switch Statement

패턴 매칭과 관련되어 Switch를 Enum과 매치해서 사용하면 코드 가독성을 높이고 안전한 데이터 분기 처리할 수 있습니다.

directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
default:
    print("default")
}

Iterating over Enumeration Cases

Enum에 정의 시 CaseIterable 프로토콜을 채택하면 allCases 속성을 통해 모든 Enum의 케이스들을 배열로 사용할 수 있습니다.

 

아래의 예에서 Beverage Enum의 모든 케이스를 포함하는 컬렉션에 액세스하기 위해 Beverage.allCases를 작성합니다.

다른 컬렉션처럼 allCases를 사용할 수 있습니다. 컬렉션의 요소는 Enum 유형의 인스턴스이므로 이 경우 Beverage 값입니다.

위의 예는 케이스가 몇 개인지 세고, 아래의 예는 for-in 루프를 사용하여 모든 케이스를 반복합니다.

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")

for beverage in Beverage.allCases {
    print(beverage)
}
// coffee
// tea
// juice

Associated Values

연관값(Associated Values)는 각 Enum 케이스에 추가적인 데이터를 저장할 수 있게 해줍니다. 이때, 각 케이스마다 각기 다른 데이터 타입의 값을 저장할 수 있어, 보다 유연하게 데이터를 다룰 수 있게 합니다.

 

예를 들어, 아래와 같이 Barcode Enum을 정의하여 했다고 가정해 봅시다.

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

 

그러면 아래 코드와 같이 productBarcode 변수를 선언하여 Barcode 타입으로 .upc값을 할당했을 때 연관값으로 (8, 85909, 51226, 3) 값을 함께 저장하게 됩니다.

var productBarcode = Barcode.upc(8, 85909, 51226, 3)

 

이번엔 productBarcode 변수에 Barcord.qrCode 값을 ABCDEFGHIJKLMNOP 연관값과 함께 저장됩니다.

productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

 

switch 구문을 활용하면 저장된 연관값들을 추출할 수 있습니다.

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode).")
}
// "QR code: ABCDEFGHIJKLMNOP." 추출

Raw Values

원시값(Raw Value)은 Enum 선언 시 미리 채워넣어주는 값을 의미합니다. 여기서 원시값들은 동일한 타입으로 저장됩니다.

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}
Note
원시값(Raw Value)과 연관값(Associated Value)는 값의 할당 시점 측면에서 다릅니다.
원시값의 경우, Enum 정의 시 미리 코드에 값을 할당하지만 연관값의 경우, 새로운 Enum 변수가 생성될 때 값이 할당된다는 차이가 있습니다.

참고사이트

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations#Initializing-from-a-Raw-Value (Swift 공식 문서 - Enumerations)