Enum
열거형은 연관된 항목들을 묶어서 표현할 수 있는 타입입니다. 열거형은 배열이나 딕셔너리 같은 타입과는 다르게 프로그래머가 정의해준 항목 값 외에는 추가/수정이 불가능합니다. 그렇기 때문에 딱 정해진 값만 열거형 값에 속할 수 있습니다.
즉, 일반적으로 Enum
이라고 하는 열거형은 관련 값 그룹을 사용하기 쉽게 정의하는 방법이라고 할 수 있습니다.
열거형은 다음 같은 경우에 요긴하게 사용할 수 있습니다.
- 제한된 선택지를 주고 싶을 때
- 정해진 값 외에는 입력받고 싶지 않을 때
- 예상된 입력 값이 한정되어 있을 때
열거형으로 묶을 수 있는 항목들은 주변에서 쉽게 찾아볼 수 있습니다.
- 지역 : 강원도, 경기도, 전라도, 제주도, 충청도
- 애플 : 아이폰, 아이패드, 맥북, 맥미니, 에어 팟
- 삼성 : 갤럭시, 버즈, 삼성 노트북, 갤럭시탭
- 학생 : 초등학생, 중학생, 고등학생, 대학생
자 이렇게 열거형을 통해 연관된 항목들의 그룹을 정의할 수 있다는 것을 알았죠? Swift의 열거형은 항목별로 값을 가질 수도, 가지지 않을 수도 있습니다. Swift의 열거형은 각 항목이 그 자체로 고유의 값이 될 수 있는 것이죠. 그렇기 때문에 실수로 버그가 일어날 가능성을 원천 봉쇄할 수 있습니다.
물론 열거형 각 항목이 원시 값(raw Value
)이라는 형태로(정수, 실수, 문자, 타입 등) 실제 값을 가질 수도 있습니다. 또는 연관 값(Associated Values
)을 사용하여 다른 언어에서 공용체라고 불리는 값의 묶음도 구현할 수 있습니다.
이 열거형은 Switch
구문과 만났을 때 아주 아주 멋있게 활용할 수 있습니다. Switch
구문을 조금 이따가 알아보도록 하죠!
열거형과 옵셔널
Swift의 주요 기능 중 하나인 옵셔널은 enum
으로 구현되어 있습니다.
기본 열거형
Swift의 열거형은 enum
이라는 키워드로 선언할 수 있습니다.
열거형에 대해 간단히 예를 들어보면, 어떠한 작업의 성공 또는 실패를 나타내는 코드를 작성하려는 경우, 이를 문자열로 나타낼 수 있습니다.
let result = "failure"
하지만 실수로 result
가 아닌 다른 이름을 사용하면 쓸데없는 코드들이 많이 지고 오류가 생기기 쉽습니다.
let result2 = "failed"
let result3 = "fail"
위 세 가지는 result
는 모두 다른 문자열이므로 서로 다른 코드입니다. 그래서 Enum
을 사용하여 수정되지 못하게 result
값을 정해줄 수 있습니다.
enum Result {
case success
case failure
}
이제 Result
를 사용할 때는 두 값(success
, failure
)중 하나를 선택해야 합니다.
let result4 = Result.failure
이렇게 하면 다른 문자열을 실수로 사용하는 것을 방지할 수 있습니다.
enum Apple {
case iPhone
case iPad
case AirPods
case Mac
case TrackPad
case MagicKeyBoard
}
Apple이라는 이름을 갖은 열거형에는 아이폰, 아이패드, 에어팟, 맥, 트랙패드, 매직키보드 라는 항목이 있고, 각 항목에는 그 자체가 고유의 값이며, 항목이 여러 가지라서 나열하기 어려우면 한 줄로 표현할 수 있습니다.
enum Apple {
case iPhone, iPad, AirPods, Mac, TrackPad, MagicKeyBoard
}
enum Apple {
case iPhone, iPad, AirPods, Mac, TrackPad, MagicKeyBoard
}
// 열거형 변수의 생성 및 값 변경
var MyAppleItems: Apple = .iPhone
var MyAppleItems2 = Apple.iPhone
var MyAppleitems3: Apple = Apple.iPhone
print(type(of: MyAppleItems2)) // Apple
// 같은 타입인 Apple 내부의 항목으로만 MyAppleItems의 값을 변경해줄 수 있다.
MyAppleItems = .AirPods
print(MyAppleItems) // AirPods
Enum을 사용하기 좋은 예시
1. 방향 (동쪽, 서쪽, 남쪽, 북쪽 등)
2. 오류 유형
3. 영화 장르
3. 요일(일주일에 7일만 있으므로)
Enum을 사용하기 안 좋은 예시
1. 내가 방문한 도시 목록 (이것은 배열로 작성하는 것이 좋습니다)
2. 이메일 주소(String
으로 작성하는 것이 좋습니다)
3. 학생들의 평균 점수(Double
로 작성하는것이 좋습니다)
Enum associated values ( 연관 값)
Enum
의 가장 강력한 기능 중 하나는 하나 이상의 관련 값, 즉 Enum case
를 더 자세히 설명해주는 추가 정보를 저장할 수 있는 기능입니다.
열거형 내의 항목(case
)이 자신과 연관된 값을 가질 수 있는 것이죠. 연관 값은 각 항목 옆에 소괄호로 묶어 표현할 수 있습니다. 다른 항목이 연관 값을 같는다고 모든 항목이 연관 값을 가질 필요는 없습니다.
이렇게 하면 열거 형에 추가 정보를 첨부하여 더 세부적인 데이터를 나타낼 수 있습니다. 예를 들어 다양한 종류의 활동을 저장하는 열거 형을 정의할 수 있습니다.
enum Activity {
case swimming
case running
case talking
case singing
}
만약 누군가가 말을 하고 있지만 그들이 무슨 말을 하는지 알지 못하거나, 누군가가 달리고 있다는 것을 알고 있지만 그들이 어디로 달려가고 있는지는 알지 못합니다. 이럴 때 열거 형 관련 값을 사용하여 세부 정보를 추가할 수 있습니다.
enum Activity {
case swimming
case running(destination: String)
case talking(topic: String)
case singing(volume: Int)
}
누군가가 축구에 대해 이야기하고 있다면 아래와 같이 코드를 작성할 수 있습니다.
let talking = Activity.talking(topic: "football")
다음 Weather
과 같은 세 가지 케이스가 있는 열거형을 만들 수 있습니다.
enum Weather {
case sunny
case windy(speed: Int)
case rainy(chance: Int, amount: Int)
}
이 열거형은 날씨가 화창하거나 바람이 불거나 비가 올 수 있음을 의미합니다. 바람이 불 때 바람의 속도를 정수로 저장하도록 요청합니다. 시간당 10km이든 20, 30 등이든 상관없습니다. 이렇게 세부적으로 열거형에 정보를 추가하게 되면 아래와 같이 복잡한 코드를 작성하지 않아도 됩니다.
//올바르지 않은 예시
enum Weather {
case sunny
case lightBreeze
case aBitWindy
case quiteBlusteryNow
case nowThatsAStrongWind
case thisIsSeriousNow
case itsAHurricane
}
예시
enum MainDish {
case pasta(taste: String)
case pizza(dough: String, topping: String)
case chicken(sauce: Bool)
case rice
}
var dinner: MainDish = MainDish.chicken(sauce: false)
dinner = .pasta(taste: "크림")
dinner = .pizza(dough: "씬", topping: "새우")
dinner = MainDish.rice
만약 식당 재료가 한정적이라 파스타의 맛과 피자의 도우, 토핑 등을 특정 메뉴로 한정 지으려면 아래와 같이 열거형으로 바꾸면 됩니다.
enum PastaTaste {
case cream, tomato
}
enum PizzaDough {
case cheeseCrust, thin, original
}
enum PizzaTopping {
case pepperoni, cheese, bacon
}
enum MainDish {
case pasta(pasta: PastaTaste)
case pizza(dough: PizzaDough, topping: PizzaTopping)
case chicken(sauce: Bool)
case rice
}
var dinner: MainDish = MainDish.chicken(sauce: true)
dinner = MainDish.pizza(dough: .original, topping: .pepperoni)
어때요? 열거형 안에 열거형을 넣어서 좀더 쉽게 메뉴를 고를 수 있게 되었습니다.
예시
enum Building {
case skyscraper(floors: Int)
}
enum Sport {
case running(distance: Int)
}
enum Instruments {
case piano(isElectric: Bool)
}
잘못된 예시
enum SocialMedia
case twitter(username: Int)
Enum raw values (원시 값)
때로는 값을 열거형에 할당하여 의미를 가질 수 있어야 합니다. 이렇게 하면 동적으로 생성하고 여러 가지 방법으로도 사용할 수 있습니다.
예를 들어 Planet
에 각 case
에 대한 정수 값(Int
)을 저장하는 열거형을 만들 수 있습니다.
enum Planet: Int {
case mercury
case venus
case earth
case mars
}
Swift에서 위 코드의 earth
는 2번째입니다. 0부터 숫자를 카운트하기 때문이죠. 만약 earth
를 가져오고 싶다면 아래와 같이 작성합니다.
let earth = Planet(rawValue: 2)
하지만 원하는 경우 하나 이상의 case
에 특정값을 할당하면 Swift가 자동으로 나머지를 생성합니다. 아래와 같이 mercury
에 정수 값 '1'을 할당해준다면 위에서부터 아래로 자동으로 숫자를 넣어주게 됩니다. 그렇기 때문에 이제 earth
는 세 번째 행성이 됩니다.
enum Planet: Int {
case mercury = 1
case venus
case earth
case mars
}
예시
enum AnimationCurve: Int {
case easeInOut
case easeIn
case easeOut
case linear
}
위의 코드를 아래처럼 한 줄로 정의할 수 있습니다.
enum AnimationCurve: Int {
case easeInOut, easeIn, easeOut, linear
}
그리고 이것들은 Raw value
유형을 일치 키시는데 아주 좋습니다.
print(AnimationCurve.easeInOut.rawValue) // 0
print(AnimationCurve.easeIn.rawValue) // 1
print(AnimationCurve.easeOut.rawValue) // 2
print(AnimationCurve.linear.rawValue) // 3
원시 값이 있는 열거형
- 각
case
에 값을 제공할 수 있다. Int raw value
는 자동으로 0부터 계산된다.raw value
는 전적으로 선택 사항이기 때문에 필수적이지 않다.raw value
에 정수와 같은 다른 것을 사용할 수 있다.raw value
를 사용하면 열거형 값을 동적으로 만들 수 있다.
항목 순회
열거형에 포함된 모든 케이스를 알아야 할 때는 열거형의 이름 뒤에 콜론 ( :
)을 작성하고 CaseIterable
프로토콜은 채택하면 됩니다. 그러면 열거형이 allCases
라는 이름의 타입 프로퍼티를 통해 모든 케이스의 컬렉션을 생성해줍니다.
enum Apple: CaseIterable {
case iPhone
case iPad
case AirPods
case Mac
case TrackPad
case MagicKeyBoard
}
let allCases: [Apple] = Apple.allCases
print(allCases)
원시 값을 갖는 열거형이면 원시값 타입 다음에 쉼표( ,
)를 쓰고 CaseIterable
을 채택해주면 됩니다.
enum Apple: String, CaseIterable {
case iPhone
case iPad
case AirPods
case Mac
case TrackPad
case MagicKeyBoard
}
let allCases: [Apple] = Apple.allCases
print(allCases)
비교 가능한 열거형
Comparable
프로토콜을 준수하는 연관 값만 갖거나 연관 값이 없는 열거형은 Comparable
프로토콜을 채택하게 되면 각 케이스를 비교할 수 있습니다.
앞에 위치한 case
가 더 작은 값이 됩니다.
enum Condition: Comparable {
case terrable
case bad
case good
case great
}
var MyCondition: Condition = Condition.great
var yourConditon: Condition = Condition.bad
if MyCondition >= yourConditon {
print("오늘응 내가 너의 상태보다 좋네..?")
} else {
print("오늘은 네가 나의 상태보다 좋구나..!")
}
MyCondition = .bad
yourConditon = .good
if MyCondition >= yourConditon {
print("오늘응 내가 너의 상태보다 좋네..?")
} else {
print("오늘은 네가 나의 상태보다 좋구나..!")
}
어때요? 어떤 식으로 비교가 되는지 알 수 있겠죠? Conditon
에서 terrable
이 최상단이기 때문에 제일 작은 값이 된 것입니다.
enum Apple: Comparable {
case iPhone(series: String)
case iPad(series: String)
case AirPods
case Mac
}
var apple: [Apple] = []
apple.append(Apple.iPhone(series: "아이폰 11 pro"))
apple.append(Apple.iPhone(series: "아이폰 12 pro"))
apple.append(Apple.iPad(series: "아이패드 pro 5세대 12.9"))
apple.append(Apple.Mac)
apple.append(Apple.AirPods)
let MyDevices: [Apple] = apple.sorted()
print(MyDevices)
/*
[ Apple.iPhone(series: "아이폰 11 pro"), Apple.iPhone(series: "아이폰 12 pro"),
Apple.iPad(series: "아이패드 pro 5세대 12.9"), Apple.AirPods, Apple.Mac ]
*/
마찬가지로 순서에 맞게 출력이 되는 것을 확인할 수 있습니다.
읽어주셔서 감사합니다🤟
'SWIFT > Grammar' 카테고리의 다른 글
Swift : 기초문법 [논리 연산자 - Logical Operators] (0) | 2021.02.20 |
---|---|
Swift : 기초문법 [ iF / else if / else ] (0) | 2021.02.20 |
Swift : 기초문법 [Empty Collections] (0) | 2021.02.19 |
Swift : 기초문법 [딕셔너리 - Dictionary] (3) | 2021.02.19 |
Swift : 기초문법 [Array vs Set vs Tuple] 간단 비교 (0) | 2021.02.19 |