하나의 주제로 연관된 데이터들이 멤버로 구성되어 있는 자료형 객체
UIDatePicker을 사용할 때(https://velog.io/@vvkkiie/iOS-UIDatePicker-DateFormatter) date picker의 스타일을 .wheels로 지정해 준 적이 있었다.
self.datePicker.preferredDatePickerStyle = .wheels
이때 UIDatePickerStyle을 Apple 공식 문서에 서치해 보면,
이렇게 열거형으로 정의되어 있음을 알 수 있음 😁
방향 - 동, 서, 남, 북
직급 - 사원, 대리, 과장, 차장, 부장, 이사, 사장
지역 - 서울, 부산, 강원, 충남, 충북, 경남, 경북, 전남, 전북, 제주
➡️ 무한히 늘어나지 않고, 미리 특정할 수 있는 값
➡️ 공통된 주제로 연관되는 값
📚 열거형 기본 정의 형식
enum 열거형 이름 {
//열거형의 멤버 정의
case 멤버값 1
case 멤버값 2
case 멤버값 3
case ...
}
📚 한꺼번에 멤버 선언도 가능함
enum Direction {
case north
case south
case east, west
}
📚 사용하기
let N = Direction.north
let S = Direction.south
let E = Direction.east
let W = Direction.west
📚 열거형 타입 명을 생략하는 경우
directionToHead
변수를 선언해 보자.
var directionToHead = Direction.west
directionToHead = .east
✏️ 이 변수는 Direction
타입임을 확인할 수 있음
✏️ 이 변수를 Direction
타입으로 정의하고 나면 이 변수에 대입될 수 있는 값은 Direction
타입에 정의된 다른 멤버값들뿐 ❗️
✏️ 열거형 타입에 속한다는 값이라는 것을 알려주기 위해 점(dot) 붙여주기
✏️ directionToHead = .east
: directionToHead
변수가 Direction
타입으로 정의된 것을 컴파일러가 알고 있기 때문에, 열거형 타입명을 생략할 수 있다
var directionSample = .east
✏️ 변수나 상수를 선언할 때, 열거형 타입을 생략하고 멤버값만 적어버리면 멤버가 어떤 열거형에 소속된 값인지를 알 수 없음
var directionSample: Direction = .west
Q. 그렇다면 이런 경우는?
A. 물론 가능하다! 타입 어노테이션을 통해 directionSample
의 타입이 Direction
임을 알 수 있기 때문
정리
- 열거형 타입으로 정의된 변수에는 열거형 타입명을 생략하고 멤버값만 대입해도 오류 발생 ❌
- 변수나 상수의 타입 어노테이션을 명시한 후, 처음부터 타입명을 생략하고 멤버값만 대입해도 오류 발생 ❌
- 타입 어노테이션 없이 변수나 상수를 초기화할 때 타입명은 생략 불가
열거형 타입으로 정의된 변수는 switch 구문에서 열거형의 멤버와 비교하는 분기 구문을 사용할 수 있음
switch 비교 대상 {
case 열거형.멤버1:
//실행할 구문
case 열거형.멤버2:
//실행할 구문
...
}
var directionToHead = Direction.west
switch directionToHead {
case Direction.north:
print("북쪽입니다")
case Direction.south:
print("남쪽입니다")
case Direction.east:
print("동쪽입니다")
case Direction.west:
print("서쪽입니다")
}
//결과: 서쪽입니다
⬇️ 얘도 가능!
switch directionToHead {
case .north:
print("북쪽입니다")
case .south:
print("남쪽입니다")
case .east:
print("동쪽입니다")
case .west:
print("서쪽입니다")
}
//결과: 서쪽입니다
✏️ switch 구문 다음의 변수를 통해 비교대상의 타입이 열거형임을 알 수 있으므로, 열거형 타입명이 생략 가능
데이터를 그대로 멤버로 사용하면 이해하기 힘든 경우, 멤버와 값을 분리하여 사용
예시를 봅시닷~~ 쉽게 이해 가넝 😆
대표적인 예로 HTTP 응답 코드가 있음.
HTTP 응답 코드의 의미
200 정상적인 응답
304 캐싱된 데이터 전송
404 존재하지 않는 URL 또는 페이지 없음
500 서버 에러
전문가가 아니라면, 이런 숫자 코드만 보고 어떤 내용인지 파악하기 힘들지 않을까? 🤔
200,300, 304, 404, 500 등을 멤버로 정의해서 열거형을 정의한다 하더라도, 필요한 내용에 맞는 코드가 뭔지 매번 찾아봐야 함.........
이를 해결하기 위해, 멤버와 값을 분리하여
멤버는 이해하기 쉬운 문자열 위주로 정의,
실질적인 값은 HTTP 응답코드(Int 타입)로 지정하고,
열거형의 멤버에 실질적인 값을 할당한다면... ❓
enum HTTPCode: Int {
case OK = 200
case NOT_MODIFY = 304
case INCORRECT_PAGE = 404
case SERVER_ERROR = 500
}
✏️ 멤버에 별도의 값을 대입할 때는, 멤버에 대입할 값의 자료형을 열거형 타입의 선언 뒤에 타입 어노테이션으로 표현해 줘야 함(enum HTTPCode: INT
)
✏️ 열거형 HTTPCode는 멤버가 정수 형태의 값을 할당받는다는 것을 의미
rawValue
속성 활용HTTPCode.OK.rawValue //200
HTTPCode.NOT_MODIFY.rawValue //304
HTTPCode.INCORRECT_PAGE.rawValue //404
HTTPCode.SERVER_ERROR.rawValue //500
Rank
열거형을 선언하고, 첫 번째 멤버에만 1의 값을 할당해 봅시닷
enum Rank: Int {
case one = 1
case two, three, four, five
}
멤버 two
~five
모두 아무 값을 대입하지 않았음에도
1에서부터 차례대로 +1 값을 증가시키며 값을 가짐
Rank.one.rawValue //1
Rank.two.rawValue //2
Rank.three.rawValue //3
Rank.four.rawValue //4
Rank.five.rawValue //5
첫 번째 멤버만 10으로 지정하면,
10에서부터 차례대로 +1 값을 증가시키며 값을 가짐
Rank.one.rawValue //10
Rank.two.rawValue //11
Rank.three.rawValue //12
Rank.four.rawValue //13
Rank.five.rawValue //14
열거형 객체를 사용하는 시점에서 멤버에 보조 값을 설정할 수 있는 방법
ImageFormat
열거형을 선언해 봅시닷
enum ImageFormat {
case JPEG
case PNG(Bool)
case GIF(Int, Bool)
}
✏️ 이미지 포맷을 정의하는 열거형임
✏️ PNG
는 배경값이 투명한 PNG
와 투명하지 않은 PNG
포맷으로 나뉨
✏️ GIF
도 사용된 컬러 수와, 애니메이션 여부에 따라 나눌 수 있음
✏️ 이러한 특성을 모두 반영하여 멤버를 정의하면 멤버의 수가 매~~우 늘어난닷
✏️ 이때 연관 값을 사용하면 적은 멤버 수로 다양한 포맷 처리 가능
var newImage = ImageFormat.JPEG
newImage = .PNG(true)
newImage = .GIF(256, true)
enum HTTPCode: Int {
case OK = 200
case NOT_MODIFY = 304
case INCORRECT_PAGE = 404
case SERVER_ERROR = 500
//연산 프로퍼티
var value: String {
return "HTTPCode number is \(self.rawValue)"
}
//인스턴스 메서드
func getDescription() -> String {
switch self {
case .OK:
return "응답이 성공했습니다. HTTP 코드는 \(self.rawValue)입니다"
case .NOT_MODIFY:
return "응답이 성공했습니다. HTTP 코드는 \(self.rawValue)입니다"
case .INCORRECT_PAGE:
return "응답이 성공했습니다. HTTP 코드는 \(self.rawValue)입니다"
case .SERVER_ERROR:
return "응답이 성공했습니다. HTTP 코드는 \(self.rawValue)입니다"
}
}
//타입 메서드
static func getName() -> String {
return "This Enumeration is HTTPCode"
}
}
var response = HTTPCode.NOT_MODIFY
response = .OK
response.value //HTTPCode number is 200"
response.getDescription() //응답이 성공했습니다. HTTP 코드는 200입니다
HTTPCode.getName() //This Enumeration is HTTPCode
✏️ getDescription()
메서드는 인스턴스 메서드 성격이므로 response
에서 호출
✏️ getName()
메서드는 타입 메서드이므로 열거형 타입 자체에서 호출
🔗
꼼꼼한 재은씨의 Swift: 문법편