티스토리 뷰

Swift

[Swift] Enum

XXIN-dev 2021. 2. 20. 20:50

나는 C#으로 한창 게임 프로그래밍을 배울 시절에 Enum를 많이 사용했던 것 같다. Enum은 case마다 각각의 정수값을 지정할 수 있고, 기본값으로 0, 1, 2 ... 가 지정되어 있어서 순서가 있는 게임 프로그래밍에 유용하게 사용했었다. Swift도 C#과 동일하게 Enum를 가지고 있는데, 사용하는 방식이 꽤 달라서 Swift속에서의 Enum사용법을 한 번 알아보려고 한다.

 

🙋🏼‍♀️ What is Enum?

열거형 관련된 값으로 이루어진 그룹을 공통의 형으로(type) 선언해 형 안전성(type-safety)을 보장하는 방법으로 코드를 다룰 수 있게 해줍니다. C나 Objective-C가 Integer값들로 열거형을 구성한 것에 반해 Swift에서는 case값이 string, character, integer, floting 값들을 사용할 수 있습니다. 열거형은 1급 클래스 형(first-class types)이어서 계산된 프로퍼티(computed properties)를 제공하거나 초기화를 지정하거나, 초기 선언을 확장해 사용할 수 있습니다.

The Swift Language Guide에 따르면, Enum은 해당 뜻을 가진다고 한다. 쉽게 정리하자면,

 

  • Eumerations 에서 따온 용어로 '열거형'이라고 해석.
  • 관련 있는 값을 묶어둔 타입
    - 타입이기 때문에 대문자 CamelCase로 나타내줘야 함
    - case는 소문자 CamelCase로 나타냄
  • 정수 뿐만 아니라 Hashable protocol를 따르는 모든 타입이 raw value로 지정 가능
    - Swift 4.1부터 Struct, Enum에 대해서 컴파일러가 자동으로 hashValue값과 == 연산자를 구현해준다.
    - 사용자가 직접 구현 가능
  • 형 안정성이 보장됨
  • 상태를 나타내기에 좋은 enum

 

🖼  선언 방식

enum Coffee { 
	case vanilla, dolce, cappuccino 
    case latte 
    case mocha 
    case americano 
    case dripCoffee 
} 

let coffee = Coffee.latte coffee = .mocha
  • 한 줄로 선언이 가능
  • 처음에 타입을 명시하고 나면 .mocha형식으로만 사용해도 해당 타입을 알아서 가져옴

 

🖍  RawValue

Raw value은 해당 enum에 선언된 타입에 맞는 value 값들이다.

enum Coffee: Int { 
	case vanilla = 1, dolce, cappuccino 
    case latte 
    case mocha 
    case americano 
    case dripCoffee 
} 

해당 코드는 Vanilla가 1의 Raw Value를 가짐.
  • Integer값의 경우에는 한 숫자만 선언하고 나머지값을 선언하지 않으면 나머지값은 선언한 숫자 뒤로 점진적으로 +1된 값을 가짐.(암묵적 RawValue 선언)
  • String의 경우에는 선언되지 않으면 해당 case값을 가짐(latte = latte를 가짐)
  • RawValue를 통해서 값을 초기화할 경우,
let coffee = Coffee(rawValue: 10) 

- 만약 해당값에 맞는 값이 enum에 지정되어 있지 않다면 nil를 출력 
- 초기화한 인스턴스 = optional이기 때문에!

optional이기 때문에, 해당 값을 사용할 때는 optional를 뗄 수 있는 장치를 해줘야 한다.

let coffee: Coffee? = Coffee(rawValue: 10) 

if let coffee: Coffee = Coffee(rawValue: 10){ 
	print(rawValue) 
} else { 
	print("unknown") 
}

 

📒 Method 추가

Enum 선언할 때, method도 함께 선언이 가능하다.

enum Coffee: Int { 
	case vanilla = 1, dolce, cappuccino 
    case latte 
    case mocha 
    case americano 
    case dripCoffee 
    
    func cup() -> String { 
    	if self.rawValue > 3 { 
        	return "i don't want it" 
        } else { 
        	return "i like it" 
        } 
    } 
} 

let coffee = Coffee.americano 
coffee.cup() // "i don't want it"

 

🖌 Associated Value

Enum 타입에 User가 추가적인 정보값을 할당할 수 있다.

enum School { 
	case student(String, String, int) 
    case professor(String, int) 
} 

let stud = School.student("Tom", "2012345", 20) 
let prof = School.professor("Jack", 56)

 

☑️ Optional

⭐️⭐️optional은 enum타입이다.
public enum Optional<Wrapped> { 
	case none 
    case some(Wrapped) 
}

따라서, 값과 없는 값을 포함하고 있고, Optional이라는 enum으로 감싸져 있는 것.

 


🛠 Switch문

enum형식은 switch문으로 편리하게 나타내어진다.

  • enum의 모든 패턴들을 빠짐없이 다룰 수 있음
  • switch문에는 enum안에 들어있는 모든 case들이 들어있어야 하고
  • 만약 하나라도 없을 시에는 default를 꼭 사용해줘야 함
  • 안그러면 error!!⭐️
enum Coffee { 
	case vanilla, dolce, cappuccino 
    case latte 
    case mocha 
    case americano 
    case dripCoffee 
} 

let coffee = Coffee.latte 

switch coffee { 
case .vanilla: 
	print("Vanilla") 
case .dolce: 
	print("Dolce") 
case .cappuccino: 
	print("Cappuccino") 
case .latte:
	print("Latte") 
default: 
	print("None") 
} // Prints "Latte"

enum 속에 있는 method에도 switch문을 포함할 수 있다.

enum Coffee: Int { 
	case vanilla = 1, dolce, cappuccino 
    case latte 
    case mocha 
    case americano 
    case dripCoffee 
    
    func cup() -> String { 
    	switch self { 
        case .vanilla:
        	print("Vanilla") 
        case .dolce: 
        	print("Dolce") 
        case .cappuccino: 
        	print("Cappuccino") 
        case .latte: 
        	print("Latte") 
        } 
    }
}

Associated Value에서도 switch문을 사용한다.

  • Associated Value를 꺼내오는 방법은
    1. if-case문을 사용
    2. switch문을 사용
enum School { 
	case student(String, String, int) 
    case professor(String, int) 
}

let stud = School.student("Tom", "2012345", 20) 
let prof = School.professor("Jack", 56) 

switch stud { 
case .student(let name, let id, let age): 
	print("\(name), \(id), \(age)") 
case .professor(let name, let age): 
	print("\(name)님 안녕하세요.") 
} // Prints "Tom, 2012345, 20"

 

🤔 왜 enum엔 Switch?

  1. if문을 사용하는 것보다 가독성이 좋기에!
  2. 새로운 case가 추가되었을 때 대응하기에 좋다!





잘못된 점과 피드백은 댓글로 주시면 감사하겠습니다.

참고:
https://jusung.gitbook.io/the-swift-language-guide/language-guide/08-enumerations
https://devxoul.gitbooks.io/ios-with-swift-in-40-hours/content/Chapter-3/enums.html

'Swift' 카테고리의 다른 글

[Swift] Property  (0) 2021.02.21
[Swift] Struct와 Class의 차이  (0) 2021.02.19
링크
최근에 올라온 글
최근에 달린 댓글