본문 바로가기

iOS/Swift

Swift 공식문서 8. Enumeration

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations

 

Documentation

 

docs.swift.org


Overview

  • 열거형은 연관성 있는 값들의 그룹을 위한 공통 타입
  • 열거형은 값 타입(Value Type)
  • 열거형에 원시 값(raw value)을 제공할 수 있다.
    • String, Character, Int, Float, Double
  • 열거형은 1급 객체이다.
    • 1급 객체 (first-class citizen)
      1. 변수나 데이터에 할당할 수 있어야 한다.
      2. 객체의 인자로 넘길 수 있어야 한다.
      3. 객체의 리턴값으로 리턴할 수 있어야 한다.
  • 계산 프로퍼티, 인스턴스 메서드 지원 가능
  • 생성자 정의, Extesnsion, 프로토콜 채택 가능

Syntax

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

enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
  • C나 Obj-C와 다르게 정수 값이 기본적으로 설정되지 않는다.

Iterating over Enumeration Cases

  • CaseIterable 프로토콜을 채택한 열거형은 allCases 프로퍼티(Array)로 모든 케이스에 접근할 수 있다.
    • 일반적으로 associated value가 없는 열거형에 채택
enum Beverage: CaseIterable {
    case coffee, tea, juice
}

let numberOfChoices = Beverage.allCases.count

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

Associated Values

  • 열거형의 케이스와 함께 저장되는 다른 타입의 값
  • 어떠한 타입도 함께 사용될 수 있고 각 케이스마다 다른 타입을 사용할 수도 있다.
  • switch 문과 함께 사용해서 해당 값에 있는 내용을 추출할 수 도 있다.
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8,85090,51226,4)
productBarcode = .qrCode("<https://github.com/hk-bae>")

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).")
}

Raw Value

  • Associated value가 열거형 타입이 여러 타입으로 이루어진 값을 저장하는 방법이라면 Raw value는 기본 값으로 미리 선언해 둘 수 있는 타입
enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}
  • 각각의 케이스마다 raw value고유한 값이어야 한다.
  • raw value는 String, Character 또는 정수나 부동 소수점 숫자 타입일 수 있다.
  • assoicated value는 타입만 정해두고 생성 시 채워주는 것이고 raw value 처음 정의할 때 미리 채워진 값으로 설정

Implicitly Assigned Raw Value

  • 열거형의 Raw Value가 String 또는 Int일 경우, 모든 케이스에 대해 Raw Value를 선언하지 않아도 된다.
  • Int
    • 첫 번째 케이스에 아무 값도 설정하지 않으면 0을 부여
    • n번째 케이스에 값이 부여되어 있지 않으면 n-1 번째 케이스에 +1을 한 값을 부여
  • String
    • 열거형 case명을 String값으로 부여

 

RawReprsentable

 

RawRepresentable | Apple Developer Documentation

A type that can be converted to and from an associated raw value.

developer.apple.com

 

Overview

  • 연관된 raw value로 변환되거나, raw value로부터 변환될 수 있는 타입
  • 원래의 RawRepresentable 타입의 값을 잃지 않는다.
  • Obj-C 및 기존 API와의 상호 운용을 간소화하고, Equtable, Comparable, Hashable 같은 다른 프로토콜 채택을 쉽게 해 준다.

 

Enumerations with Raw Values

  • 문자열, 정수 또는 부동 소수점을 raw type으로 가진 모든 열거형에 대해 Swift 컴파일러는 자동으로 RawRepresentable를  준수
  • 열거형을 정의할 때, raw type상속받도록 정의
  • 리터럴을 사용하여 하나 이상의 케이스에 값을 지정할 수도 있음
enum Counter: Int {
    case one = 1, two, three, four, five
}
  • RawRepresentable 프로토콜에 선언된 init?(rawValue:) 이니셜라이저 사용 가능
  • 실패 가능 이니셜라이저(failable) : 해당 열거형의 케이스와 대응하지 않는 많은 원시 타입 값이 존재
for i in 3...6 {
    print(Counter(rawValue: i))
}
// Prints "Optional(Counter.three)"
// Prints "Optional(Counter.four)"
// Prints "Optional(Counter.five)"
// Prints "nil"

 

 

Recursive Enummerations

  • 어떤 열거형의 케이스에 Associated Value로 자신의 열거형 타입이 들어간 경우
  • 케이스 앞에 indirect 키워드를 삽입해 컴파일러에게 알려야 함
    • indirection : 값을 직접 저장하거나 사용하는 대신, 그 값이 위치한 메모리 주소를 참조하는 방식
    • 열거형은 value semantics메모리에서 고정된 크기를 갖는다.
    • 재귀적인 구조에서는 컴파일러가 해당 구조의 크기를 결정할 수 없다.
    • 이를 해결하기 위해 indirect 키워드를 사용하여 간접 참조를 통해 재귀적인 데이터를 관리

indirect 마킹 안함

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
  • 열거형의 시작 부분에 indirect를 마킹 : 연관 값을 가진 모든 열거형 케이스에 대해 indirection 활성화

 

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

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)  // 5 + 4
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))  // (5 + 4) * 2

 

[참고]

  • Struct에서는 재귀적으로 자기 자신의 타입을 가질 수가 없다.

 

 

'iOS > Swift' 카테고리의 다른 글

Swift 공식문서 9. Structures and Classes  (1) 2024.10.05
Swift 공식문서 7. Closures  (3) 2024.09.26
Swift 공식문서 6. Functions  (0) 2024.09.20
Swift - In-Out 파라미터  (0) 2024.09.20
Swift 공식문서 5. Control Flow  (0) 2024.09.19