티스토리 뷰
정의
열거형은 관련된 값들의 그룹에 대한 공통 타입을 정의하고 안전한 타입(type-safe)이 된 해당 값들로 코드 내에서 사용할 수 있게 해줍니다.
각 열거 case 별로 값이 제공 된경우, 값의 타입은 String, Character, Int, Float가 될 수 있습니다.
열거형은 자체로 1급 클래스 유형 이어서 초기화를 정의 할 수도 있고, 초기기능을 확장할 수도 있고, 표준 기능을 제공하기 위해 프로토콜을 준수 할 수도 있습니다.
어렵다...
열거형 문법
열거형은 enum 키워드를 사용하여 정의 합니다.
enum Enumeration {
// enumeration 정의는 여기에 !
}
다음은 (동, 서, 남, 북) 네 가지 방향을 갖는 CompassPoint 열거형 선언의 예시 입니다.
enum CompassPoint {
case north
case south
case east
case west
}
NOTE
Swift 열거형은 C나 Objective-C와 다르게 case 별로 integer 값을 할당 하지 않습니다.
예시의 CompassPoint를 보면, north, south, east, west가 암시적으로 0,1,2,3 값을 갖지 않고,
각 case 별로 명시적으로 정의된 타입의 고유한 값을 가집니다.
아래 처럼 여러 case를 한줄로 작성 할 수도 있습니다.
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn
}
각 열거형 정의는 새로운 타입을 정의 하므로,
다른 타입들과 같이 열거형의 이름은 대문자로 시작하게 만들고, 단수형으로 이름을 짓습니다.
var directionToHead = CompassPoint.west
directionToHead는 초기화 될때 CompassPoint의 값들중 하나로 타입 추론이 됩니다.
한번 directionToHead가 CompassPoint로 선언되면,
점 문법을(dot syntax) 이용해 값을 할당하는 축약형 문법을 사용할 수 있습니다.
directionToHead = .east
Switch 구문에서 열거형 값 매칭
(Matching Enumeration Values with a Switch Statement)
각 열거형 값들을 switch 구문에 매칭 시킬 수 있습니다.
enum CompassPoint {
case north
case south
case east
case west
}
var directionToHead = CompassPoint.west // 한번 선언 됨으로써 CompassPoint 값 인지함
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")
}
// Print: Watch out for penguins
switch문은 반드시 모든 경우들을 포함 해야 합니다.
만약 위의 case에서 한 case라도 빠지게 될 경우 컴파일 되지 않습니다.
모든 case를 일일히 작성하기 보다 예외 처리를 하고 싶다면 default case를 제공함으로써 처리되지 않는 case를 피할수 있습니다.
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn
}
// 예외처리 (default)
let somePlant = Planet.venus
switch somePlant {
case .earth:
print("여기 사람 살아요")
default:
print("여기 외계인 살아요!!")
}
// Print: 여기 외계인 살아요!!
// earth case
let somePlant = Planet.earth
switch somePlant {
case .earth:
print("여기 사람 살아요")
default:
print("여기 외계인 살아요!!")
}
// Print: 여기 사람 살아요
관련값 (Associated Values)
열거형의 각 case별로 custom type의 정보를 저장할 수 있습니다.
아래 두 가지 바코드 예제를 보면서 설명을 하면,
첫번째 바코드의 경우 아래 숫자를 (Int) 4가지 구분으로 나누어진 바코드 종류가 있고
QR 코드의 경우 약 3,000개의 문자로 (String) 구성되어 있습니다.
위 바코드 두 가지를 열거형으로 정의 하자면 아래와 같이 할 수 있습니다.
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
위와 같은 정의는 실제로 정수나 문자열 값을 주지 않습니다.
상수, 변수화 시켜 Barcode.upc , Barcode.qrCode 중 하나일때 , 그와 관련된 값들의 타입만 정의 합니다.
upc
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode로 불리는 새로운 변수를 만들고 Barcode.upc에 (8, 85909, 51226, 3) 튜플 값을 할당 합니다.
다른 바코드의 타입으로 할당 할 수도 있습니다.
qr
productBarcode = .qrCode("ABCDEFGHIGKLMNOP")
위와 같이하면 Barcode.upc 였던 정수 값은 Barcode.quCode의 문자열 값으로 바뀝니다.
Barcode 타입의 상수, 변수는 upc나 qrCode로 저장 할 수는 있으나 한번에 둘 중 하나만 저장할 수 있습니다.
관련 값은 switch 문을 사용하여 상수, 변수로 선언 할 수 있습니다.
아래 처럼 변수/상수로 원하는 이름을 정의해서 사용할 수 있습니다.
// productBarcode = .qrCode("ABCDEFGHIGKLMNOP")
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: ABCDEFGHIGKLMNOP
위 처럼 case안의 관련 값이 모두 상수거나 변수이면 let, var를 앞으로 빼내어 축약해 사용할 수 있습니다.
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check): // let을 앞으로 이동
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case let .qrCode(productCode): // let을 앞으로 이동
print("QR code: \(productCode)")
}
// QR code: ABCDEFGHIGKLMNOP
Raw 값 (Raw Values)
case에 기본값을 지정할 수 있습니다.
다음 예시는 ASCII 값을 열거형에 저장 하는 예제 입니다.
enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "\n"
case CarriageReturn = "\r"
}
위에서는 Character 타입으로 정의 했지만, 이 외에도 String, Int, Float등 타입을 사용할 수도 있습니다.
각 Raw값은 열거형 선언 내에서 유니크한 값이어야 합니다. (중복 불가)
NOTE
Raw값은 관계값과 다릅니다.
Raw값은 코드에서 열거형을 처음 선언할 때 정의 되어 항상 같은 값을 갖게 됩니다.
관계값은 같은 case라도 생성될 때 달라질 수 있습니다.
암시적으로 할당된 Raw값 (Implicitly Assigned Raw Values)
열거형을 다룰 때 raw값으로 String이나 Int 값을 사용할 수 있는데, raw값이 없을 경우.
Swift에서는 자동으로 값을 할당해주기 때문에, 각 case별로 값을 할당해줄 필요는 없습니다.
앞에 Planet 예시를 이어서 해보겠습니다.
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn
}
print(Planet.mercury.rawValue) // 1
print(Planet.earth.rawValue) // 3
열거형 Planet에 Int 타입을 지정했고,
mercury에 1이 라는 raw값을 할당했습니다.
이후 case에는 암시적으로 raw값이 2 .. 3.. 4 순으로 증가 하게 됩니다.
만약 String 타입을 지정하게 되면,
case의 text가 자동으로 raw값으로 할당 됩니다.
아래 예시는 앞에 CompassPoint 예시를 이어 작업한 겁니다.
enum CompassPoint: String {
case north
case south
case east
case west
}
print(CompassPoint.west.rawValue) // west
Raw 값을 이용한 초기화 (Initializing from a Raw Value)
raw값을 이용하여 열거형 변수를 초기화 할 수 있습니다.
아래 예제는 raw값 4를 갖는 값을 열거형 변수의 초기 값으로 지정합니다.
let possiblePlanet = Planet(rawValue: 4) // mars
print(possiblePlanet) // Optional(__lldb_expr_36.Planet.mars)
모든 Int 값에 맞는 planet을 찾을수 있는게 아니기 때문에, raw값 초기자는 항상 optional 열거형 케이스를 반환합니다.
if let possiblePlanet = Planet(rawValue: 4) {
print(possiblePlanet) // mars
} else {
print("else")
}
만약 열거형에 없는 raw값을 초기자로 지정하면 nil 이 됩니다.
//enum Planet: Int {
// case mercury = 1, venus, earth, mars, jupiter, saturn
//}
let planetPosition = 100
if let somePlanet = Planet(rawValue: planetPosition) {
switch somePlanet {
case .earth: // let planetPosition = 3 일때 해당
print("지구는 사람 사는곳")
default: // let planetPosition = 1,2,4,5,6 일때 해당
print("사람 못 사는곳")
}
} else {
print("\(planetPosition)번째는 열거된 Planet에 없음")
}
// 100번째는 열거된 Planet에 없음
재귀 열거자 (Recursive Enumerations)
재귀 열거자는 다른 열거 인스턴스를 관계 값으로 갖는 열거형 입니다.
case 앞에 indirect 키워드를 붙여서 표시합니다.
enum Arithmetic {
case number(Int)
indirect case addition(Arithmetic, Arithmetic)
indirect case multiplication(Arithmetic, Arithmetic)
}
관계 값을 가지는 모든 열거형 case에 indirect 키워드를 붙이고 싶다면
enum 앞에 indirect를 붙여줍니다.
indirect enum Arithmetic { // enum 앞에 indirect 추가
case number(Int)
case addition(Arithmetic, Arithmetic)
case multiplication(Arithmetic, Arithmetic)
}
위 열거형은 세 가지 종류의 산술 표현식 (숫자, 덧셈, 곱셈)을 저장할 수 있습니다.
아래 예제는 ( 5 + 4 ) * 2 를 재귀 열거자로 표현한 예 입니다.
let five = Arithmetic.number(5)
let four = Arithmetic.number(4)
let sum = Arithmetic.addition(five, four)
let product = Arithmetic.multiplication(sum, Arithmetic.number(2))
다음은 재귀 열거자를 처리 하는 함수 입니다.
func evaluate(_ expression: Arithmetic) -> Int {
switch expression {
case let .number(val):
return val
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right): // left = 9 , right = 2
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
'iOS' 카테고리의 다른 글
[iOS] Alamofire - GET (0) | 2022.02.13 |
---|---|
[iOS] UITextField placeholder 위치 조정 (0) | 2022.02.11 |
[iOS] CocoaPods 설치 및 실행 (0) | 2022.02.06 |
[Swift] 클로저 (Closure) (2) - Escaping Closure, Autoclosure (0) | 2022.02.02 |
[Swift] 클로저 (Closure) (1) (0) | 2022.01.30 |
- Total
- Today
- Yesterday
- Swift Error Handling
- Combine: Asynchronous Programming with Swift
- Swift 알고리즘
- CS 네트워크
- 2023년 회고
- Swift init
- Swift RIBs
- Class
- swift programmers
- swift reduce
- Swift final
- 원티드 프리온보딩
- RIBs tutorial
- swift (programmers)
- ios
- RTCCameraVideoCapturer
- Swift Leetcode
- Swift joined
- Swift 프로퍼티
- removeLast()
- Swift joined()
- Swift inout
- Swift ModernRIBs
- swift protocol
- swift 고차함수
- Swift 내림차순
- Swift
- swift property
- Swift 프로그래머스
- iOS error
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |