Swift Enumerations
Enumerations - Associated Values, Raw Values
1. Enumeration Syntax π©βπ»
1. Enumerations in Swift
Enumeration
μ μ°κ΄λ κ°λ€μ κ³΅ν΅ νμ
μΌλ‘ κ·Έλ£Ήνν΄ Type-Safe
ν μ½λλ₯Ό μμ±νλλ‘ λλλ€.
Swift μμ Enumeration μ μ£Όμ΄μ§ κ°μ΄ String
, Character
, Interger
, Float
μ΄λ€ κ²μ΄λ
μ μ₯ν μ μλ€. λ€λ₯Έ νλ‘κ·Έλλ° μΈμ΄μμ unions λλ variants κ° μλνλ κ²κ³Ό κ°λ€.
Swift μμ Enumeration μ κ·Έ μμ²΄λ‘ First-Class Types
λ‘ μ ν΅μ μΌλ‘ Classes
μμλ§ μ 곡λλ
λ§μ κΈ°λ₯μ μ±ννλ€.
- Initializers
- Computed Properties
- Instance methods
- Extend their original implementation
- Confirm to protocols
Syntax
enum SomeEnumeration {
case one
case two
case three
}
enum SomeEnumeration {
case one, two, three
}
- Enumeration μ μ
Type
μ λ§λ€μ΄ λΈλ€. λ°λΌμ Swift μ λ€λ₯Έ Types μ λ§μ°¬κ°μ§λ‘ μ΄λ¦μλλ¬Έμλ‘ μμ
νλ€.- Enumeration μ
Singleton
μ κΈ°λ°μΌλ‘ νλ―λ‘ μ΄λ¦ μμ μλͺ νκ² μ½νλλ‘ λ³΅μν(plural)μ΄ μλλ¨μν(singular)μ μ¬μ©
νλ€.
2. Enumeration Examples
enum CompassPoint {
case north
case south
case east
case west
}
Swift μ Enumeration μ λ€λ₯Έ μΈμ΄μ λ¬λ¦¬ μμμ μΌλ‘ integer value(0, 1, 2, β¦)λ₯Ό ν λΉνμ§ μλλ€.
case
λμ¨μ ν μκΈ° μμ μ κ°
μΌλ‘ κ°λλ€.
κ° case λ λ€μκ³Ό κ°μ΄ ,
λ₯Ό μ΄μ©ν΄ ν μ€λ‘ μ μ μ μλ€.
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
μμμ μ μν CompassPoint
, Planet
μ κ°κ° νλμ Type μ λ§λ€μ΄λμΌλ©°, λμ μλ‘ λ€λ₯Έ Type μ΄λ€.
var directionToHead = CompassPoint.west
print("Type of directionToHead is '\(type(of: directionToHead))'")
μ΄λ―Έ Type μ΄ μ ν΄μ§ κ²½μ°, Dot Syntax
(.
)λ₯Ό μ΄μ©ν μ μλ€.
var directionToHead = CompassPoint.west
print("directionToHead is '\(directionToHead)'") // directionToHead is west
directionToHead = .east
print("directionToHead is '\(directionToHead)'") // directionToHead is east
var anotherDirectionToHead: CompassPoint
anotherDirectionToHead = .south
print("anotherDirectionToHead is '\(anotherDirectionToHead)'") // anotherDirectionToHead is south
2. Matching Enumeration Values with Switch π©βπ»
1. Matching with Switch
Enumeration μ Switch
λ₯Ό μ΄μ©ν΄ λ€μκ³Ό κ°μ΄ 맀μΉμν¬ μ μλ€.
enum CompassPoint {
case east, west, south, north
}
var directionToHead: 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")
}
Watch out for penguins
2. Switch must be exhaustive
directionToHead = .south
switch directionToHead { // Switch must be exhaustive - add missing case: '.north'
case .south:
print("Watch out for penguins")
}
south λ₯Ό μ μΈν case λ₯Ό μ κ±°νλ€. directionToHead λ νμ¬ south λκΉ λ¬Έμ μμ κ²
κ°μ§λ§, Swift λ μ΄ Switch
κ° μμ νμ§ μμ κ²μ λ°κ²¬νκ³ compile-error
λ₯Ό λ°μμν¨λ€.
λ°λΌμ, μ¬μ©λμ§ μλλΌλ λ€μκ³Ό κ°μ΄ case miss-matching
μ΄ μΌμ΄λμ§ μλλ‘ λ€μκ³Ό κ°μ΄
μ²λ¦¬ν΄μΌνλ€.
switch directionToHead {
case .south:
print("Watch out for penguins")
default:
print("This direction is not south")
}
Switch
κ°Enumeration
μ λ€λ£° λcase
λμμ ν΄μΌ(exhaustive)
νλ€.
3. Iterating over Enumeration Cases π©βπ»
Enumeration μ CaseIterable
νλ‘ν μ½μ μ±νν¨μΌλ‘μ¨ ν΄λΉ Enum Type μ λͺ¨λ cases λ₯Ό
κ°λ Collection
μ μμ±νλ€.
Syntax
enum SomeEnumeration: CaseIterable {
case one, two, three
}
enum Beverage: CaseIterable {
case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available\n")
for beverage in Beverage.allCases {
print(beverage)
}
3 beverages available
coffee
tea
juice
4. Associated Values π©βπ»
λλ‘λ Enumeration μ cases κ° μκΈ° μμ μ κ° μΈμ λ€λ₯Έ νμ
μ κ°μ ν¨κ» μ μ₯
νλ κ²μ΄ μ μ©ν λκ° μλ€.
μ΄λ₯Ό Associated Value
λΌκ³ νλ©°, μ΄λ λ€λ₯Έ νλ‘κ·Έλλ° μΈμ΄μμ unions, tagged unions, variants λ‘
μλ €μ§ κ²λ€κ³Ό μ μ¬νλ€.
Syntax
enum SomeEnumeration {
case one(Int)
case two(Int, Int)
case three(String)
}
1. Barcode Systems for Examples
1D barcodes in UPC
format, 2D barcodes in QR code
format λ₯Ό μ΄μ©ν΄ μ€λͺ
νλ€.
- Barcodes UPC
- Barcodes QR code
μ°μ UPC λ 1D λ°μ½λλ‘ numebr system, manufacturer code, product code, check μμΌλ‘
μ΄λ€μ§ 4κ°μ Int
κ·Έλ£ΉμΌλ‘ ꡬμ±λμ΄μ§λ€.
λ€μμΌλ‘ QR code λ 2D λ°μ½λλ‘ 2,953μ μ΄λ΄μ μ΄λ ν ISO 8859-1
λ¬Έμλ μ μ₯ν μ μλ€.
2. Adopt Associated Values
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
Barcode enum type μ΄ κ°μ§ μ μλ κ°μ λ€μκ³Ό κ°λ€.
- (Int, Int, Int, Int)
4 Integer Tuple
νμ μupc
String
νμ μqrCode
νμ§λ§ Barcode enum
μ΄ κ°λ κ°μ μ¬μ€μ Associated Value
μ νμ
μ μ μν λΏ μ΄ κ° μ체λ μ½λμ μ΄λ ν
μ€μ§μ μλ―Έλ κ°μ§ μλλ€. Beverage
μ λΉκ΅ν΄λ³΄μ.
enum Beverage: CaseIterable {
case coffee, tea, juice
}
var myBeverage: Beverage
myBeverage = .coffee
Beverage enum
type μ coffee, tea, juice λ₯Ό μκΈ° μμ μ κ°μΌλ‘ κ°λλ€.
μ΄ κ°μ κ° μμ²΄κ° μ½λμμμ μ€μ§μ μλ―Έλ₯Ό κ°λλ€.
μ΄λ²μλ μ Beverage λ₯Ό κΈ°μ΅νλ©° Barcode λ₯Ό μ΄ν΄λ³΄μ.
var productBarcode: Barcode
productBarcode = .upc(8, 85909, 51226, 3)
print("productBarcode is '\(productBarcode)'") // productBarcode is 'upc(8, 85909, 51226, 3)'
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
print("productBarcode is '\(productBarcode)' now") // productBarcode is 'qrCode("ABCDEFGHIJKLMNOP")' now
Barcode
νμ μ λ³μproductBarcode
λ₯Ό μ μΈνλ€.- λ³μ productBarcode μ Associated Tuple Value λ‘
(8, 85909, 51226, 3)
λ₯Ό κ°λBarcode.upc
κ°μ ν λΉνλ€. - μ΄λ²μλ λ³μ productBarcode λ Associated Tuple Value
("ABCDEFGHIJKLMNOP")
λ₯Ό κ°λBarcode.qrCode
κ°μ ν λΉνλ€.
μ΄λ₯Ό μ 리νλ©΄ λ€μκ³Ό κ°λ€.
Beverage μ κ°
coffee
κ° μ€μ§μ μΈ κ°μ κ°λ κ²κ³Ό λ¬λ¦¬ Barcode μ κ°upc
λqrCode
λ κ° μ체λ‘μ¨λ μ€μ§μ μΈ μλ―Έκ° μλ€. Barcode μ κ° upc λ qrCode λ κ°μ§ μ μλAssociated Value μ Type μ μ μ
ν λΏμ΄λ€.
μ€μ λ‘ μλ―Έλ₯Ό κ°λ κ°μ(8, 85909, 51226, 3)
λλ("ABCDEFGHIJKLMNOP")
μ κ°μAssociated Tuple Value
κ° μ μ₯νκ³ μλ κ°μ΄λ€.λν Beverage νμ μ μμ λλ λ³μκ° κ°μΌλ‘
coffee
μtea
λ₯Ό λμμ κ°μ§ μ μλ κ²κ³Ό λ§μ°¬κ°μ§λ‘, Barcode νμ μ μμ λλ λ³μ μμupc
λqrCode
λ κ°μ§μ κ°μ λͺ¨λ μ μ₯ν μλ μμ§λ§ λμμ κ°μ§ μλ μλ€.
3. Switch Statements with Associated Values
μμμ μ΄ν΄λ³Έ Enumeration μ Switch μ 맀μΉνλ κ²κ³Ό λμΌνλ€. λ¨, μ΄ κ²½μ° μ€μ§μ μΈ κ°μ΄ Associated Values
μ΄ κ°μ case
λ΄μμ μ¬μ©νκΈ° μν΄μλ let
λλ var
μ ν λΉν΄μΌνλ€.
var productBarcode: Barcode
productBarcode = .upc(8, 85909, 51226, 3)
printBarcode(productBarcode) // UPC: 8, 85909, 51226, 3.
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
printBarcode(productBarcode) // QR code: ABCDEFGHIJKLMNOP.
func printBarcode (_ productBarcode: Barcode) {
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).")
}
}
λ§μ½, Associated Values
μ λΆκ° νμν κ²½μ° λ€μκ³Ό κ°μ΄ κ°μ₯ μμ μ μΈνλ κ²μΌλ‘ λμ ν μ μλ€.
var productBarcode: Barcode
productBarcode = .upc(8, 85909, 51226, 3)
printBarcode(productBarcode) // UPC: 8, 85909, 51226, 3.
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
printBarcode(productBarcode) // QR code: ABCDEFGHIJKLMNOP.
func printBarcode (_ productBarcode: Barcode) {
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
}
Summary of Associated Values
Associated Values λ Enumeration μ cases κ° μ¨μ ν μκΈ° μμ μ κ°μΌλ‘ κ°λ λμ λ€λ₯Έ νμ μ κ°μ κ°κ² νλ©°, μ΄λ Enumeration μ cases κ°μ κ°μ§ μ μλ Associated Values μ types λ₯Ό μ μνλ€.
Associated Values λ₯Ό μ΄μ©νλ©΄ μλ‘ λ€λ₯Έ νμ μ κ°μ νλμ Enumeration μ μ μ₯ν μ μλ€.
λ¨, μλ‘ λ€λ₯Έ νμ μ λμμ μ μ₯νλ κ²μ μλλ€.
5. Raw Values π©βπ»
μμμ Associated Values λ cases κ° μκΈ° μμ μ κ° μΈμ λ€λ₯Έ κ°μ κ°λ κ²μ λ¬Όλ‘ , μλ‘ λ€λ₯Έ νμ
μ κ°
μ
μ μ₯νκΈ° μν΄ μ΄λ»κ² μ μν΄μΌνλμ§λ₯Ό 보μ¬μ£Όμλ€.
μ΄λ²μλ Associated Values
μ λμ μ€ νλλ‘, cases
κ° μκΈ° μμ μ κ° μΈμ λ€λ₯Έ κ°μ κ°μ§ μ μλ λ°©λ²μΌλ‘
Raw Values
λ₯Ό μκ°νλ€. Associated Values μ λ§μ°¬κ°μ§λ‘ μκΈ° μμ μ κ° μΈμ λ€λ₯Έ κ°μ κ°λλ‘ νλ κ²μ
λμΌνμ§λ§, Associated Values μ λ¬λ¦¬ λμΌ νμ
μ κ°
λ§ cases
λ‘ μ μ₯ν μ μλ€.
Raw Values
λ₯Ό μ μνλ λ°©λ²μ enum
μ μ μν¨κ³Ό λμμ default values
λ₯Ό μ μνλ κ²μ΄λ€.
Syntax
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
enum SomeEnumeration: Int {
case one = 1
case two = 2
case three = 3
}
print(SomeEnumeration.one) // One
print(SomeEnumeration.one.rawValue) // 1
enum SomeEnumeration: String {
case one = "νλ"
case two = "λ"
case three = "μ
"
}
print(SomeEnumeration.one) // One
print(SomeEnumeration.one.rawValue) // νλ
Raw Values
λString
,Character
,Integer
,Floating-Point Number
νμ μ΄ κ°λ₯νλ€.
Raw Values
λUnique
ν΄μΌνλ€.
1. Implicitly Assigned Raw Values
Enumerations λ Raw Values
λ₯Ό λ³λλ‘ μ§μ νμ§ μμΌλ©΄ 첫 case μ μμμ (implicit) 0
μ ν λΉνλ€.
λ§μ½, Integer
λλ String
Types μ λ°μ΄ν°λ₯Ό λͺ
μμ (explicit)μΌλ‘ μ§μ ν΄ μ μ₯ν κ²½μ° λͺ¨λ cases μ
κ°μ λͺ
μν νμ μμ΄ νλμ κ°μ λͺ
μνλ©΄ μ΄ν κ°μ κ·Έ κ°μ κΈ°λ°μΌλ‘ μλμΌλ‘ μμμ μΌλ‘ ν λΉλλ€.
- Integer Raw Value
Raw Values λ₯Ό Integer Type μΌλ‘ μ§μ ν μ무λ κ°λ λͺ
μνμ§ μμ κ²½μ° Swift λ μμμ μΌλ‘ 첫 case
λ₯Ό
0
μΌλ‘ ν λΉλλ€.
μ°
enum Planet: Int {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
print(Planet.mercury.rawValue) // 0
print(Planet.venus.rawValue) // 1
print(Planet.neptune.rawValue) // 7
Raw Values λ₯Ό Integer Type μΌλ‘ μ§μ ν case μ κ°μ λͺ
μμ μΌλ‘ μ μ₯ν κ²½μ°, λͺ
μμ μΌλ‘ μ μ₯ν case
μ
λ€μ μμλΆν° 1μ© μ¦κ°μν¨λ€.
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
print(Planet.mercury.rawValue) // 1
print(Planet.venus.rawValue) // 2
print(Planet.neptune.rawValue) // 8
μλμ κ°μ κ²½μ° 10, 20, 30, 40, ...
μ΄ μλ 10, 20, 21, 22, ...
μ΄λ―λ‘ μ£Όμνλ€.
enum Planet: Int {
case mercury = 10, venus = 20, earth, mars, jupiter, saturn, uranus, neptune
}
print(Planet.mercury.rawValue) // 10
print(Planet.venus.rawValue) // 20
print(Planet.neptune.rawValue) // 26
λ§μ°¬κ°μ§λ‘ μλμ κ²½μ°λ 2, 3, 4, 5, 6, ..., 9
κ° μλλΌ 0, 1, 2, 5, 6, ..., 9
μ΄λ―λ‘ μ£Όμνλ€.
enum Planet: Int {
case mercury, venus, earth, mars = 5, jupiter, saturn, uranus, neptune
}
print(Planet.mercury.rawValue) // 0
print(Planet.venus.rawValue) // 5
print(Planet.neptune.rawValue) // 9
- String Raw Value
Raw Values λ₯Ό String Type μΌλ‘ μ§μ ν κ²½μ° μμμ μΌλ‘ κ° casesμ μ΄λ¦
μ΄ String
μΌλ‘ ν λΉλλ€.
enum CompassPoint: String {
case east, west, south, north
}
print(CompassPoint.east) // east
print(CompassPoint.east.rawValue) // east
print(type(of: CompassPoint.east)) // CompassPoint
print(type(of: CompassPoint.east.rawValue)) // String
2. Initializing from a Raw Value
- With specific cases
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
let possiblePlanet = Planet.uranus
print(possiblePlanet) // uranus
λͺ ννκ²
case
λ₯Ό μ§μ νλ―λ‘, μΈμ λ ν΄λΉνλ case μ Enumeration μInstance
λ‘ μμ±νλ€.
- With Raw Values
Raw Value λ₯Ό λ°μ μΌμΉνλ Enumeration μ Enumeration μ case λ₯Ό Optional Instance
λ‘ μμ±νλ€.
enum Planet: Int {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
let possiblePlanet = Planet(rawValue: 7)
print(possiblePlanet as Any) // Optional(__lldb_expr_18.Planet.neptune)
let impossiblePlanet = Planet(rawValue: 8)
print(impossiblePlanet as Any) // nil
λ°λΌμ λ€μκ³Ό κ°μ΄ Optional Binding
μ μ΄μ©ν΄ μμ νκ² μ²λ¦¬νλ κ²μ΄ μ’λ€.
var positionToFind = 3
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)")
}
Mostly harmless
var 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)")
}
There isn't a planet at position 11
var positionToFind = 11
let isThisSafePlanet = { (planetNumber: Int) -> Bool in
guard let somePlanet = Planet(rawValue: planetNumber) else {
print("There isn't a planet at position \(planetNumber)")
return false
}
switch somePlanet {
case .earth:
print("Mostly harmless")
return true
default:
print("Not a safe place for humans")
return false
}
}
let safe = isThisSafePlanet(positionToFind)
print("safe: \(safe)")
There isn't a planet at position 11
safe: false
6. Recursive Enumerations π©βπ»
Enumeration μ case κ° λ€μ μκΈ° μμ μ Associated Values λ‘ κ°μ§ λ μ΄λ₯Ό Recursive Enumerations
λΌ νλ©°,
λ°λμ indirect
ν€μλλ₯Ό λͺ
μν΄μΌνλ€.
enum ArithmeticExpression { // Recursive enum 'ArithmeticExpression' is not marked 'indirect'
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
indirect
ν€μλ μμ΄ μ μΈνλ©΄ Swift-compiler μ μν΄ μλ¬κ° λ°μλλ€.
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
λ°λμ Recursive-case μμ indirect
ν€μλλ₯Ό λΆμ¬μ€μΌνλ€.
λ§μ½, enum ν€μλ μμ indirect
ν€μλλ₯Ό μ μΈνλ©΄ λͺ¨λ cases μ indirect λ₯Ό μμμ μΌλ‘ μ μΈν μ μλ€.
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
μ Enumeration ArithmeticExpression.Type
μ λ€μ 3 κ°μ§μ arithmetic expressions
(μ°μ ννμ)μ
μ μ₯ν μ μλ€.
- a plain number
- the addition of two expressions
- the multiplication of two expressions
μ΄ μ€ addition
κ³Ό multiplication
cases λ λ€μ arithmetic expressions λ₯Ό Associated Values λ‘
κ°μ§λ―λ‘ ννμμ μ€μ²©μ νμ©ν΄ Recursive μνλ₯Ό λ§λ λ€.
(5 + 4) * 2
λ₯Ό ArithmeticExpression.Type λ₯Ό μ΄μ©ν΄ μ μΈν΄λ³΄μ. λ°μ΄ν°κ° μ€μ²©(nested)
λλ―λ‘,
Enumeration μμ μ€μ²©(nested)
μ΄ κ°λ₯ν΄μΌνλ€.
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
Recursive Structure
λ₯Ό κ°μ§ λ°μ΄ν°λ₯Ό λ€λ£¨λ κ°μ₯ μ§κ΄μ μΈ λ°©λ²μ Recursive Function
μ μ΄μ©νλ κ²μ΄λ€.
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case .number(let value): return value
case let .addition(lhs, rhs): return evaluate(lhs) + evaluate(rhs)
case let .multiplication(lhs, rhs): return evaluate(lhs) * evaluate(rhs)
}
}
evaluate(_:)
μ 첫 λ²μ§Έ case λ Optional Binding νλ― ArithmeticExpression.Type μΌλ‘λΆν°
Int
λ₯Ό λ°ννλ€.
evaluate(_:)
μ λ λ²μ§Έμ μΈ λ²μ§Έ case λ 첫 λ²μ§Έ case λ₯Ό μ·¨νλλ‘ Recursive Function
μΌλ‘ μμ±λμλ€.
ArithmeticExpression
μ evaluate(_:)
μ κ΅¬μ‘°κ° λͺ¨λ Recursive
μΈ κ²μ νμΈν μ μλ€.
print(evaluate(five)) // 5
print(evaluate(four)) // 4
print(evaluate(sum)) // 9
print(evaluate(product)) // 18
Reference
- βEnumerations.β The Swift Programming Language Swift 5.7. accessed Nov. 1, 2022, Swift Docs Chapter 7 - Enumerations.