-
EnumerationsiOS/Swift 공식문서 2022. 2. 16. 22:32
Enumeration Syntax
enum
키워드를 사용하여 열거형을 정의할 수 있다.enum CompassPoint { case north case south case east case west }
여러 case를 콤마로 구분하여 나열할 수 있다.
enum Planet { case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune }
note
Swift의 경우 열거형의 case들이 정수값을 가지지 않는다. 대신 case들은 해당 열거형 타입(ex. CompassPoint, Planet 등)으로 선언된 온전한 값이다.
각 열거형 정의는 새로운 타입을 정의한다. 따라서 Swift의 다른 타입처럼, 열거형의 이름은 대문자로 시작해야 한다. 아래 예시에서
directionToHead
라는 변수는 타입 추론을 통해CompassPoint
타입을 갖게 된다.var directionToHead = CompassPoint.west
타입이 이미 정해진 이후에는 다음과 같이 타입을 생략할 수 있다.
directionToHead = .east
Matching Enumeration Values with a Switch Statement
열거형의 값을
switch
문에서 사용할 수 있다. switch 문은 값의 모든 case를 다 포함해야 하기 때문에 열거형의 값 중 하나라도 빠져 있다면 컴파일되지 않는다.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") } // Prints "Watch out for penguins"
아래와 같이 여러 값들을
default
로 처리하는 방법도 있다.let somePlanet = Planet.earth switch somePlanet { case .earth: print("Mostly harmless") default: print("Not a safe place for humans") } // Prints "Mostly harmless"
Iterating over Enumeration Cases
열거형 정의 시
CaseIterable
키워드를 사용하면allCases
프로퍼티를 통하여 모든 값의 컬렉션을 사용할 수 있다. 이 경우 열거형은CaseIterable
프로토콜을 따르게 된다.enum Beverage: CaseIterable { case coffee, tea, juice } let numberOfChoices = Beverage.allCases.count print("\(numberOfChoices) beverages available") // Prints "3 beverages available" for beverage in Beverage.allCases { print(beverage) } // coffee // tea // juice
Associated Values
열거형의 각
case
에 대하여 추가적인 정보를 저장할 수 있는데, 이 추가적인 정보를 관련 값(associated value)이라고 한다. 예를 들어 바코드가 4개의 정수값으로 이루어진 upc와, 문자들로 구성된 QR코드 2종류로 나뉜다면, 바코드를 다음과 같은 열거형으로 정의할 수 있다. 이와 같이 같은 타입이지만 다른 형태의 값을 가지는 case를 만들 수 있다.enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) }
UPC, QR코드는 아래와 같이 선언할 수 있다.
var productBarcode = Barcode.upc(8, 85909, 51226, 3) productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
관련 값은 switch case 문에서 상수/변수로 선언할 수 있다.
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).") } // Prints "QR code: ABCDEFGHIJKLMNOP."
Raw Values
열거형의
case
는 기존 타입의 raw 값을 가질 수 있다. case의 값은 모두 같은 타입이어야 한다.enum ASCIIControlCharacter: Character { case tab = "\t" case lineFeed = "\n" case carriageReturn = "\r" }
Implicitly Assigned Raw Values
정수나 문자열을 raw 값으로 사용할 경우 각
case
에 대하여 명시적으로 raw 값을 할당할 필요가 없다. 정수를 raw 값으로 사용하는 경우 각case
의 암시적 값은 이전case
값보다 1만큼 큰 값이다. 첫번째case
의 경우 값을 명시하지 않으면 0으로 설정된다.enum Planet: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune }
문자열이 사용될 경우, 각 case 이름의 문자열이 raw 값이 된다. raw 값은
rawValue
프로퍼티로 접근할 수 있다.enum CompassPoint: String { case north, south, east, west } let sunsetDirection = CompassPoint.west.rawValue // sunsetDirection is "west"
Initializing from a Raw Value
열거형을 raw 값으로 정의한 경우, raw 값으로 사용한 타입의 값을 받는 initializer를 사용할 수 있다. 해당 값을 가지는
case
가 존재하면 해당case
를 반환하고, 없으면nil
을 반환한따.nil
을 반환할 수 있기 때문에 타입은 optional이다.case
를 반환하지 못할 수 있기 때문에 failable initializer라고 부른다.let possiblePlanet = Planet(rawValue: 7) // possiblePlanet is of type Planet? and equals Planet.uranus let positionToFind = 11 if let somePlanet = Planet(rawValue: positionToFind) { switch somePlanet { case .earth: print("Mostly harmless") default: print("Not a safe place for humans") } } else { print("There isn't a planet at position \(positionToFind)") } // Prints "There isn't a planet at position 11"
Recursive Enumerations
최소 한 개의
case
에서 관련 값으로 다른 열거형 인스턴스를 가지는 열거형을 말한다. 해당case
는indirect
라는 키워드를 적어서 재귀적인case
임을 나타낸다.enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) }
모든 case에
indirect
표시를 하고 싶으면enum
키워드 앞에indirect
키워드를 적는 방법도 있다.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) 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) } } print(evaluate(product)) // Prints "18"
Reference
https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html
'iOS > Swift 공식문서' 카테고리의 다른 글
Properties (0) 2022.02.18 Structures and Classes (0) 2022.02.17 Closures (0) 2022.02.16 Functions (0) 2022.02.15 Control Flow (0) 2022.02.15